From 1487578b0843ec08e9f39904274ca433d1ac7da0 Mon Sep 17 00:00:00 2001 From: Ivan Gerasimov Date: Mon, 22 Aug 2016 22:16:54 +0300 Subject: [PATCH 01/51] 8164366: ZoneOffset.ofHoursMinutesSeconds() does not reject invalid input Reviewed-by: scolebourne, ntv, coffeys --- .../share/classes/java/time/ZoneOffset.java | 21 +++++++++--------- .../time/tck/java/time/TCKZoneOffset.java | 22 ++++++++++++++++++- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/time/ZoneOffset.java b/jdk/src/java.base/share/classes/java/time/ZoneOffset.java index c5d15ef8ccc..9f2e9c2d356 100644 --- a/jdk/src/java.base/share/classes/java/time/ZoneOffset.java +++ b/jdk/src/java.base/share/classes/java/time/ZoneOffset.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -375,15 +375,15 @@ public final class ZoneOffset } else if ((minutes > 0 && seconds < 0) || (minutes < 0 && seconds > 0)) { throw new DateTimeException("Zone offset minutes and seconds must have the same sign"); } - if (Math.abs(minutes) > 59) { - throw new DateTimeException("Zone offset minutes not in valid range: abs(value) " + - Math.abs(minutes) + " is not in the range 0 to 59"); + if (minutes < -59 || minutes > 59) { + throw new DateTimeException("Zone offset minutes not in valid range: value " + + minutes + " is not in the range -59 to 59"); } - if (Math.abs(seconds) > 59) { - throw new DateTimeException("Zone offset seconds not in valid range: abs(value) " + - Math.abs(seconds) + " is not in the range 0 to 59"); + if (seconds < -59 || seconds > 59) { + throw new DateTimeException("Zone offset seconds not in valid range: value " + + seconds + " is not in the range -59 to 59"); } - if (Math.abs(hours) == 18 && (Math.abs(minutes) > 0 || Math.abs(seconds) > 0)) { + if (Math.abs(hours) == 18 && (minutes | seconds) != 0) { throw new DateTimeException("Zone offset not in valid range: -18:00 to +18:00"); } } @@ -411,7 +411,7 @@ public final class ZoneOffset * @throws DateTimeException if the offset is not in the required range */ public static ZoneOffset ofTotalSeconds(int totalSeconds) { - if (Math.abs(totalSeconds) > MAX_SECONDS) { + if (totalSeconds < -MAX_SECONDS || totalSeconds > MAX_SECONDS) { throw new DateTimeException("Zone offset not in valid range: -18:00 to +18:00"); } if (totalSeconds % (15 * SECONDS_PER_MINUTE) == 0) { @@ -696,11 +696,12 @@ public final class ZoneOffset * The comparison is "consistent with equals", as defined by {@link Comparable}. * * @param other the other date to compare to, not null - * @return the comparator value, negative if less, postive if greater + * @return the comparator value, negative if less, positive if greater * @throws NullPointerException if {@code other} is null */ @Override public int compareTo(ZoneOffset other) { + // abs(totalSeconds) <= MAX_SECONDS, so no overflow can happen here return other.totalSeconds - totalSeconds; } diff --git a/jdk/test/java/time/tck/java/time/TCKZoneOffset.java b/jdk/test/java/time/tck/java/time/TCKZoneOffset.java index c121079dae6..76466431033 100644 --- a/jdk/test/java/time/tck/java/time/TCKZoneOffset.java +++ b/jdk/test/java/time/tck/java/time/TCKZoneOffset.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -419,6 +419,21 @@ public class TCKZoneOffset extends AbstractDateTimeTest { ZoneOffset.ofHoursMinutesSeconds(-19, 0, 0); } + @Test(expectedExceptions=DateTimeException.class) + public void test_factory_int_hours_minutes_seconds_minutesMinValue() { + ZoneOffset.ofHoursMinutesSeconds(0, Integer.MIN_VALUE, -1); + } + + @Test(expectedExceptions=DateTimeException.class) + public void test_factory_int_hours_minutes_seconds_secondsMinValue() { + ZoneOffset.ofHoursMinutesSeconds(0, 0, Integer.MIN_VALUE); + } + + @Test(expectedExceptions=DateTimeException.class) + public void test_factory_int_hours_minutes_seconds_minutesAndSecondsMinValue() { + ZoneOffset.ofHoursMinutesSeconds(0, Integer.MIN_VALUE, Integer.MIN_VALUE); + } + //----------------------------------------------------------------------- @Test public void test_factory_ofTotalSeconds() { @@ -437,6 +452,11 @@ public class TCKZoneOffset extends AbstractDateTimeTest { ZoneOffset.ofTotalSeconds(-18 * 60 * 60 - 1); } + @Test(expectedExceptions=DateTimeException.class) + public void test_factory_ofTotalSeconds_minValue() { + ZoneOffset.ofTotalSeconds(Integer.MIN_VALUE); + } + //----------------------------------------------------------------------- // from() //----------------------------------------------------------------------- From 4a9aefb851b513131812fe800fd20ec59c3b986e Mon Sep 17 00:00:00 2001 From: Steve Drach Date: Thu, 18 Aug 2016 17:18:21 -0700 Subject: [PATCH 02/51] 8164389: jdk.nio.zipfs.JarFileSystem does not completely traverse the versioned entries in a multi-release jar file Reviewed-by: psandoz --- .../classes/jdk/nio/zipfs/JarFileSystem.java | 2 +- jdk/test/jdk/nio/zipfs/jarfs/JFSTester.java | 124 ++++++++++++++++++ .../jdk/nio/zipfs/jarfs/root/dir1/leaf1.txt | 1 + .../jdk/nio/zipfs/jarfs/root/dir1/leaf2.txt | 1 + .../jdk/nio/zipfs/jarfs/root/dir2/leaf3.txt | 1 + .../jdk/nio/zipfs/jarfs/root/dir2/leaf4.txt | 1 + .../nio/zipfs/jarfs/v9/root/dir1/leaf1.txt | 1 + .../nio/zipfs/jarfs/v9/root/dir1/leaf2.txt | 1 + .../nio/zipfs/jarfs/v9/root/dir2/leaf3.txt | 1 + .../nio/zipfs/jarfs/v9/root/dir2/leaf4.txt | 1 + 10 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 jdk/test/jdk/nio/zipfs/jarfs/JFSTester.java create mode 100644 jdk/test/jdk/nio/zipfs/jarfs/root/dir1/leaf1.txt create mode 100644 jdk/test/jdk/nio/zipfs/jarfs/root/dir1/leaf2.txt create mode 100644 jdk/test/jdk/nio/zipfs/jarfs/root/dir2/leaf3.txt create mode 100644 jdk/test/jdk/nio/zipfs/jarfs/root/dir2/leaf4.txt create mode 100644 jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf1.txt create mode 100644 jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf2.txt create mode 100644 jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf3.txt create mode 100644 jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf4.txt diff --git a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java index 1e05e84e40f..2826f96f4ff 100644 --- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java +++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java @@ -165,8 +165,8 @@ class JarFileSystem extends ZipFileSystem { walk(inode.child, process); } else { process.accept(inode); - walk(inode.sibling, process); } + walk(inode.sibling, process); } /** diff --git a/jdk/test/jdk/nio/zipfs/jarfs/JFSTester.java b/jdk/test/jdk/nio/zipfs/jarfs/JFSTester.java new file mode 100644 index 00000000000..881e27dbd4f --- /dev/null +++ b/jdk/test/jdk/nio/zipfs/jarfs/JFSTester.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8164389 + * @summary walk entries in a jdk.nio.zipfs.JarFileSystem + * @modules jdk.jartool/sun.tools.jar + * @run testng JFSTester + */ + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +public class JFSTester { + private URI jarURI; + private Path jarfile; + + @BeforeClass + public void initialize() throws Exception { + String userdir = System.getProperty("user.dir","."); + jarfile = Paths.get(userdir, "test.jar"); + String srcdir = System.getProperty("test.src"); + String[] args = ( + "-cf " + + jarfile.toString() + + " -C " + + srcdir + + " root --release 9 -C " + + srcdir + + System.getProperty("file.separator") + + "v9 root" + ).split(" +"); + new sun.tools.jar.Main(System.out, System.err, "jar").run(args); + String ssp = jarfile.toUri().toString(); + jarURI = new URI("jar", ssp, null); + } + + @AfterClass + public void close() throws IOException { + Files.deleteIfExists(jarfile); + } + + @Test + public void testWalk() throws IOException { + + // no configuration, treat multi-release jar as unversioned + Map env = new HashMap<>(); + Set contents = doTest(env); + Set baseContents = Set.of( + "This is leaf 1.\n", + "This is leaf 2.\n", + "This is leaf 3.\n", + "This is leaf 4.\n" + ); + Assert.assertEquals(contents, baseContents); + + // a configuration and jar file is multi-release + env.put("multi-release", "9"); + contents = doTest(env); + Set versionedContents = Set.of( + "This is versioned leaf 1.\n", + "This is versioned leaf 2.\n", + "This is versioned leaf 3.\n", + "This is versioned leaf 4.\n" + ); + Assert.assertEquals(contents, versionedContents); + } + + private Set doTest(Map env) throws IOException { + Set contents; + try (FileSystem fs = FileSystems.newFileSystem(jarURI, env)) { + Path root = fs.getPath("root"); + contents = Files.walk(root) + .filter(p -> !Files.isDirectory(p)) + .map(this::pathToContents) + .collect(Collectors.toSet()); + } + return contents; + } + + private String pathToContents(Path path) { + try { + return new String(Files.readAllBytes(path)); + } catch (IOException x) { + throw new UncheckedIOException(x); + } + } +} diff --git a/jdk/test/jdk/nio/zipfs/jarfs/root/dir1/leaf1.txt b/jdk/test/jdk/nio/zipfs/jarfs/root/dir1/leaf1.txt new file mode 100644 index 00000000000..05f9592a818 --- /dev/null +++ b/jdk/test/jdk/nio/zipfs/jarfs/root/dir1/leaf1.txt @@ -0,0 +1 @@ +This is leaf 1. diff --git a/jdk/test/jdk/nio/zipfs/jarfs/root/dir1/leaf2.txt b/jdk/test/jdk/nio/zipfs/jarfs/root/dir1/leaf2.txt new file mode 100644 index 00000000000..19229fa2322 --- /dev/null +++ b/jdk/test/jdk/nio/zipfs/jarfs/root/dir1/leaf2.txt @@ -0,0 +1 @@ +This is leaf 2. diff --git a/jdk/test/jdk/nio/zipfs/jarfs/root/dir2/leaf3.txt b/jdk/test/jdk/nio/zipfs/jarfs/root/dir2/leaf3.txt new file mode 100644 index 00000000000..724fae66d88 --- /dev/null +++ b/jdk/test/jdk/nio/zipfs/jarfs/root/dir2/leaf3.txt @@ -0,0 +1 @@ +This is leaf 3. diff --git a/jdk/test/jdk/nio/zipfs/jarfs/root/dir2/leaf4.txt b/jdk/test/jdk/nio/zipfs/jarfs/root/dir2/leaf4.txt new file mode 100644 index 00000000000..3fafaadeda0 --- /dev/null +++ b/jdk/test/jdk/nio/zipfs/jarfs/root/dir2/leaf4.txt @@ -0,0 +1 @@ +This is leaf 4. diff --git a/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf1.txt b/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf1.txt new file mode 100644 index 00000000000..9092c1883d3 --- /dev/null +++ b/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf1.txt @@ -0,0 +1 @@ +This is versioned leaf 1. diff --git a/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf2.txt b/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf2.txt new file mode 100644 index 00000000000..9a2d266edf1 --- /dev/null +++ b/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf2.txt @@ -0,0 +1 @@ +This is versioned leaf 2. diff --git a/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf3.txt b/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf3.txt new file mode 100644 index 00000000000..6491cae8b83 --- /dev/null +++ b/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf3.txt @@ -0,0 +1 @@ +This is versioned leaf 3. diff --git a/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf4.txt b/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf4.txt new file mode 100644 index 00000000000..aa5563cb709 --- /dev/null +++ b/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf4.txt @@ -0,0 +1 @@ +This is versioned leaf 4. From 4fc198725593df5b6a1ab6fb912e91364a7eb80b Mon Sep 17 00:00:00 2001 From: Jesper Wilhelmsson Date: Fri, 19 Aug 2016 17:19:47 +0200 Subject: [PATCH 03/51] 8164124: [BACKOUT] G1 does not implement millis_since_last_gc which is needed by RMI GC Reviewed-by: jprovino --- hotspot/src/share/vm/gc/g1/g1Analytics.cpp | 6 +----- hotspot/src/share/vm/gc/g1/g1Analytics.hpp | 1 - hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp | 16 ++-------------- hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp | 2 +- .../src/share/vm/gc/shared/genCollectedHeap.cpp | 14 +++++++------- 5 files changed, 11 insertions(+), 28 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1Analytics.cpp b/hotspot/src/share/vm/gc/g1/g1Analytics.cpp index 8214a4bfa55..c43b4169e49 100644 --- a/hotspot/src/share/vm/gc/g1/g1Analytics.cpp +++ b/hotspot/src/share/vm/gc/g1/g1Analytics.cpp @@ -316,12 +316,8 @@ size_t G1Analytics::predict_pending_cards() const { return get_new_size_prediction(_pending_cards_seq); } -double G1Analytics::oldest_known_gc_end_time_sec() const { - return _recent_prev_end_times_for_all_gcs_sec->oldest(); -} - double G1Analytics::last_known_gc_end_time_sec() const { - return _recent_prev_end_times_for_all_gcs_sec->last(); + return _recent_prev_end_times_for_all_gcs_sec->oldest(); } void G1Analytics::update_recent_gc_times(double end_time_sec, diff --git a/hotspot/src/share/vm/gc/g1/g1Analytics.hpp b/hotspot/src/share/vm/gc/g1/g1Analytics.hpp index 3f9a37a98e7..a22d0dd72bd 100644 --- a/hotspot/src/share/vm/gc/g1/g1Analytics.hpp +++ b/hotspot/src/share/vm/gc/g1/g1Analytics.hpp @@ -155,7 +155,6 @@ public: void update_recent_gc_times(double end_time_sec, double elapsed_ms); void compute_pause_time_ratio(double interval_ms, double pause_time_ms); - double oldest_known_gc_end_time_sec() const; double last_known_gc_end_time_sec() const; }; diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index a267098ed86..d84e1000763 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -28,7 +28,6 @@ #include "classfile/symbolTable.hpp" #include "code/codeCache.hpp" #include "code/icBuffer.hpp" -#include "gc/g1/g1Analytics.hpp" #include "gc/g1/bufferingOopClosure.hpp" #include "gc/g1/concurrentG1Refine.hpp" #include "gc/g1/concurrentG1RefineThread.hpp" @@ -2474,19 +2473,8 @@ size_t G1CollectedHeap::max_capacity() const { } jlong G1CollectedHeap::millis_since_last_gc() { - jlong now = os::elapsed_counter() / NANOSECS_PER_MILLISEC; - const G1Analytics* analytics = _g1_policy->analytics(); - double last = analytics->last_known_gc_end_time_sec(); - jlong ret_val = now - (last * 1000); - if (ret_val < 0) { - // See the notes in GenCollectedHeap::millis_since_last_gc() - // for more information about the implementation. - log_warning(gc)("Detected clock going backwards. " - "Milliseconds since last GC would be " JLONG_FORMAT - ". returning zero instead.", ret_val); - return 0; - } - return ret_val; + // assert(false, "NYI"); + return 0; } void G1CollectedHeap::prepare_for_verify() { diff --git a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp index dfef9538ba7..454f73bc0c6 100644 --- a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp +++ b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp @@ -604,7 +604,7 @@ void G1DefaultPolicy::record_collection_pause_end(double pause_time_ms, size_t c _analytics->report_alloc_rate_ms(alloc_rate_ms); double interval_ms = - (end_time_sec - _analytics->oldest_known_gc_end_time_sec()) * 1000.0; + (end_time_sec - _analytics->last_known_gc_end_time_sec()) * 1000.0; _analytics->update_recent_gc_times(end_time_sec, pause_time_ms); _analytics->compute_pause_time_ratio(interval_ms, pause_time_ms); } diff --git a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp index c1a28350047..049b675bd51 100644 --- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp @@ -1256,21 +1256,21 @@ class GenTimeOfLastGCClosure: public GenCollectedHeap::GenClosure { }; jlong GenCollectedHeap::millis_since_last_gc() { - // javaTimeNanos() is guaranteed to be monotonically non-decreasing - // provided the underlying platform provides such a time source - // (and it is bug free). So we still have to guard against getting - // back a time later than 'now'. + // We need a monotonically non-decreasing time in ms but + // os::javaTimeMillis() does not guarantee monotonicity. jlong now = os::javaTimeNanos() / NANOSECS_PER_MILLISEC; GenTimeOfLastGCClosure tolgc_cl(now); // iterate over generations getting the oldest // time that a generation was collected generation_iterate(&tolgc_cl, false); + // javaTimeNanos() is guaranteed to be monotonically non-decreasing + // provided the underlying platform provides such a time source + // (and it is bug free). So we still have to guard against getting + // back a time later than 'now'. jlong retVal = now - tolgc_cl.time(); if (retVal < 0) { - log_warning(gc)("Detected clock going backwards. " - "Milliseconds since last GC would be " JLONG_FORMAT - ". returning zero instead.", retVal); + NOT_PRODUCT(log_warning(gc)("time warp: " JLONG_FORMAT, retVal);) return 0; } return retVal; From 9517153e77e6ebbd334e3a1e475ed0f4fe5984e6 Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Mon, 22 Aug 2016 15:27:50 -0700 Subject: [PATCH 04/51] 8164589: Remove sun/rmi/runtime/Log/6409194/NoConsoleOutput.java from ProblemList Reviewed-by: jwilhelm --- jdk/test/ProblemList.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 50eb6e6b321..5bad9db84d4 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -211,8 +211,6 @@ sun/rmi/rmic/newrmic/equivalence/run.sh 8145980 generic- java/rmi/transport/dgcDeadLock/DGCDeadLock.java 8029360 macosx-all -sun/rmi/runtime/Log/6409194/NoConsoleOutput.java 8164124 windows-all - ############################################################################ # jdk_security From d6dfc0bef3175d95ebcde1688ed3e357273fb28e Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 22 Aug 2016 17:22:09 -0700 Subject: [PATCH 05/51] 8164524: Correct inconsistencies in floating-point abs spec Reviewed-by: martin, bpb --- .../share/classes/java/lang/Math.java | 18 ++++++++++++++---- .../share/classes/java/lang/StrictMath.java | 18 ++++++++++++++---- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/Math.java b/jdk/src/java.base/share/classes/java/lang/Math.java index 4261bd2c3f1..37a9d8573c5 100644 --- a/jdk/src/java.base/share/classes/java/lang/Math.java +++ b/jdk/src/java.base/share/classes/java/lang/Math.java @@ -1370,8 +1370,13 @@ public final class Math { * result is positive zero. *
  • If the argument is infinite, the result is positive infinity. *
  • If the argument is NaN, the result is NaN. - * In other words, the result is the same as the value of the expression: - *

    {@code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))} + * + * @apiNote As implied by the above, one valid implementation of + * this method is given by the expression below which computes a + * {@code float} with the same exponent and significand as the + * argument but with a guaranteed zero sign bit indicating a + * positive value:
    + * {@code Float.intBitsToFloat(0x7fffffff & Float.floatToRawIntBits(a))} * * @param a the argument whose absolute value is to be determined * @return the absolute value of the argument. @@ -1389,8 +1394,13 @@ public final class Math { * is positive zero. *

  • If the argument is infinite, the result is positive infinity. *
  • If the argument is NaN, the result is NaN. - * In other words, the result is the same as the value of the expression: - *

    {@code Double.longBitsToDouble((Double.doubleToLongBits(a)<<1)>>>1)} + * + * @apiNote As implied by the above, one valid implementation of + * this method is given by the expression below which computes a + * {@code double} with the same exponent and significand as the + * argument but with a guaranteed zero sign bit indicating a + * positive value:
    + * {@code Double.longBitsToDouble((Double.doubleToRawLongBits(a)<<1)>>>1)} * * @param a the argument whose absolute value is to be determined * @return the absolute value of the argument. diff --git a/jdk/src/java.base/share/classes/java/lang/StrictMath.java b/jdk/src/java.base/share/classes/java/lang/StrictMath.java index 3ef67145d0c..1491a8478bc 100644 --- a/jdk/src/java.base/share/classes/java/lang/StrictMath.java +++ b/jdk/src/java.base/share/classes/java/lang/StrictMath.java @@ -1070,8 +1070,13 @@ public final class StrictMath { * result is positive zero. *

  • If the argument is infinite, the result is positive infinity. *
  • If the argument is NaN, the result is NaN. - * In other words, the result is the same as the value of the expression: - *

    {@code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))} + * + * @apiNote As implied by the above, one valid implementation of + * this method is given by the expression below which computes a + * {@code float} with the same exponent and significand as the + * argument but with a guaranteed zero sign bit indicating a + * positive value:
    + * {@code Float.intBitsToFloat(0x7fffffff & Float.floatToRawIntBits(a))} * * @param a the argument whose absolute value is to be determined * @return the absolute value of the argument. @@ -1089,8 +1094,13 @@ public final class StrictMath { * is positive zero. *

  • If the argument is infinite, the result is positive infinity. *
  • If the argument is NaN, the result is NaN. - * In other words, the result is the same as the value of the expression: - *

    {@code Double.longBitsToDouble((Double.doubleToLongBits(a)<<1)>>>1)} + * + * @apiNote As implied by the above, one valid implementation of + * this method is given by the expression below which computes a + * {@code double} with the same exponent and significand as the + * argument but with a guaranteed zero sign bit indicating a + * positive value:
    + * {@code Double.longBitsToDouble((Double.doubleToRawLongBits(a)<<1)>>>1)} * * @param a the argument whose absolute value is to be determined * @return the absolute value of the argument. From a4818844a91454c32eb13bcad157c82c97af24c8 Mon Sep 17 00:00:00 2001 From: Alexandre Iline Date: Mon, 22 Aug 2016 18:22:19 -0700 Subject: [PATCH 06/51] 8163126: Fix @modules in some of jdk/* tests Reviewed-by: weijun, alanb, mchung --- jdk/test/jdk/lambda/TEST.properties | 2 +- .../jdk/modules/etc/VerifyModuleDelegation.java | 16 ++++++++++------ .../scenarios/container/ContainerTest.java | 2 ++ jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java | 2 +- jdk/test/jdk/security/jarsigner/Spec.java | 3 ++- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/jdk/test/jdk/lambda/TEST.properties b/jdk/test/jdk/lambda/TEST.properties index 772348b784c..58528a633db 100644 --- a/jdk/test/jdk/lambda/TEST.properties +++ b/jdk/test/jdk/lambda/TEST.properties @@ -3,4 +3,4 @@ TestNG.dirs = . javatest.maxOutputSize = 250000 -modules = jdk.compiler +modules = jdk.compiler jdk.zipfs diff --git a/jdk/test/jdk/modules/etc/VerifyModuleDelegation.java b/jdk/test/jdk/modules/etc/VerifyModuleDelegation.java index 613a854faa2..a0a32fce292 100644 --- a/jdk/test/jdk/modules/etc/VerifyModuleDelegation.java +++ b/jdk/test/jdk/modules/etc/VerifyModuleDelegation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @summary Verify the defining class loader of each module never delegates * to its child class loader. Also sanity check java.compact2 * requires. + * @modules java.compact2 * @run testng/othervm --add-modules=ALL-SYSTEM VerifyModuleDelegation */ @@ -33,7 +34,9 @@ import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleFinder; import java.lang.module.ModuleReference; import java.lang.reflect.Layer; +import java.lang.reflect.Module; import java.util.Set; +import static java.util.stream.Collectors.toSet; import static java.lang.module.ModuleDescriptor.Requires.Modifier.*; @@ -58,8 +61,9 @@ public class VerifyModuleDelegation { .requires(Set.of(PUBLIC), "java.xml") .build(); - private static final Set MREFS - = ModuleFinder.ofSystem().findAll(); + private static final Set MREFS + = Layer.boot().modules().stream().map(Module::getDescriptor) + .collect(toSet()); private void check(ModuleDescriptor md, ModuleDescriptor ref) { assertTrue(md.requires().size() == ref.requires().size()); @@ -69,7 +73,7 @@ public class VerifyModuleDelegation { @Test public void checkJavaBase() { ModuleDescriptor md = - MREFS.stream().map(ModuleReference::descriptor) + MREFS.stream() .filter(d -> d.name().equals(JAVA_BASE)) .findFirst().orElseThrow(Error::new); @@ -78,7 +82,7 @@ public class VerifyModuleDelegation { @Test public void checkCompact2() { ModuleDescriptor md = - MREFS.stream().map(ModuleReference::descriptor) + MREFS.stream() .filter(d -> d.name().equals(JAVA_COMPACT2)) .findFirst().orElseThrow(Error::new); check(md, COMPACT2); @@ -87,7 +91,7 @@ public class VerifyModuleDelegation { @Test public void checkLoaderDelegation() { Layer boot = Layer.boot(); - MREFS.stream().map(ModuleReference::descriptor) + MREFS.stream() .forEach(md -> md.requires().stream().forEach(req -> { // check if M requires D and D's loader must be either the diff --git a/jdk/test/jdk/modules/scenarios/container/ContainerTest.java b/jdk/test/jdk/modules/scenarios/container/ContainerTest.java index 1ad5f352080..f56245413ac 100644 --- a/jdk/test/jdk/modules/scenarios/container/ContainerTest.java +++ b/jdk/test/jdk/modules/scenarios/container/ContainerTest.java @@ -26,6 +26,8 @@ * @library /lib/testlibrary * @modules jdk.jartool/sun.tools.jar * jdk.compiler + * jdk.zipfs + * java.se * @build ContainerTest CompilerUtils jdk.testlibrary.* * @run testng ContainerTest * @summary Starts a simple container that uses dynamic configurations diff --git a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java index 6e483c6e21a..6c116010ee0 100644 --- a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java +++ b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java @@ -28,7 +28,7 @@ * @library /lib/testlibrary/java/util/jar * @build Compiler JarBuilder CreateMultiReleaseTestJars * @run testng MultiReleaseJarTest - * @modules java.compiler + * @modules jdk.compiler * jdk.jartool * jdk.zipfs */ diff --git a/jdk/test/jdk/security/jarsigner/Spec.java b/jdk/test/jdk/security/jarsigner/Spec.java index a4853bf08c2..b36b90690df 100644 --- a/jdk/test/jdk/security/jarsigner/Spec.java +++ b/jdk/test/jdk/security/jarsigner/Spec.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ * @modules java.base/sun.security.tools.keytool * java.base/sun.security.provider.certpath * jdk.jartool + * jdk.crypto.ec */ import com.sun.jarsigner.ContentSigner; From 738e2b4297973230a53c033bab656eebb194be2e Mon Sep 17 00:00:00 2001 From: Robert Field Date: Mon, 22 Aug 2016 19:28:36 -0700 Subject: [PATCH 07/51] 8164596: jshell tool: jdk repo module pages to allow double-dash fix to access Jopt-simple Reviewed-by: jlahoda --- jdk/src/jdk.internal.opt/share/classes/module-info.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/jdk.internal.opt/share/classes/module-info.java b/jdk/src/jdk.internal.opt/share/classes/module-info.java index 9c8f889adf2..dc5d39b6453 100644 --- a/jdk/src/jdk.internal.opt/share/classes/module-info.java +++ b/jdk/src/jdk.internal.opt/share/classes/module-info.java @@ -24,5 +24,5 @@ */ module jdk.internal.opt { - exports jdk.internal.joptsimple to jdk.jlink; + exports jdk.internal.joptsimple to jdk.jlink, jdk.jshell; } From 928ca9c5d29a01e01d119846c44a0f8e83dfb878 Mon Sep 17 00:00:00 2001 From: Lance Andersen Date: Tue, 23 Aug 2016 10:30:16 -0400 Subject: [PATCH 08/51] 8164061: Fix @since for javax.sql.rowset.BaseRowSet and javax.sql.CommonDataSource Reviewed-by: darcy --- .../classes/javax/sql/rowset/BaseRowSet.java | 27 +---------------- .../classes/javax/sql/CommonDataSource.java | 4 --- .../javax/sql/ConnectionPoolDataSource.java | 28 +++++++++++++++++ .../share/classes/javax/sql/DataSource.java | 28 +++++++++++++++++ .../share/classes/javax/sql/XADataSource.java | 30 ++++++++++++++++++- 5 files changed, 86 insertions(+), 31 deletions(-) diff --git a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/BaseRowSet.java b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/BaseRowSet.java index 1f938621a31..b86e5be0fb7 100644 --- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/BaseRowSet.java +++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/BaseRowSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3204,7 +3204,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @since 1.4 */ public void setNull(String parameterName, int sqlType) throws SQLException { throw new SQLFeatureNotSupportedException("Feature not supported"); @@ -3240,7 +3239,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @since 1.4 */ public void setNull (String parameterName, int sqlType, String typeName) throws SQLException{ @@ -3259,7 +3257,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setBoolean(String parameterName, boolean x) throws SQLException{ throw new SQLFeatureNotSupportedException("Feature not supported"); @@ -3277,7 +3274,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setByte(String parameterName, byte x) throws SQLException{ throw new SQLFeatureNotSupportedException("Feature not supported"); @@ -3295,7 +3291,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setShort(String parameterName, short x) throws SQLException{ throw new SQLFeatureNotSupportedException("Feature not supported"); @@ -3313,7 +3308,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setInt(String parameterName, int x) throws SQLException{ throw new SQLFeatureNotSupportedException("Feature not supported"); @@ -3332,7 +3326,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setLong(String parameterName, long x) throws SQLException{ throw new SQLFeatureNotSupportedException("Feature not supported"); @@ -3350,7 +3343,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setFloat(String parameterName, float x) throws SQLException{ throw new SQLFeatureNotSupportedException("Feature not supported"); @@ -3368,7 +3360,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setDouble(String parameterName, double x) throws SQLException{ throw new SQLFeatureNotSupportedException("Feature not supported"); @@ -3387,7 +3378,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{ throw new SQLFeatureNotSupportedException("Feature not supported"); @@ -3408,7 +3398,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setString(String parameterName, String x) throws SQLException{ throw new SQLFeatureNotSupportedException("Feature not supported"); @@ -3428,7 +3417,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setBytes(String parameterName, byte x[]) throws SQLException{ throw new SQLFeatureNotSupportedException("Feature not supported"); @@ -3447,7 +3435,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setTimestamp(String parameterName, java.sql.Timestamp x) throws SQLException{ @@ -3474,7 +3461,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @since 1.4 */ public void setAsciiStream(String parameterName, java.io.InputStream x, int length) throws SQLException{ @@ -3500,7 +3486,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @since 1.4 */ public void setBinaryStream(String parameterName, java.io.InputStream x, int length) throws SQLException{ @@ -3528,7 +3513,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @since 1.4 */ public void setCharacterStream(String parameterName, java.io.Reader reader, @@ -3684,7 +3668,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * this data type * @see Types * @see #getParams - * @since 1.4 */ public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException{ @@ -3710,7 +3693,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * or STRUCT data type and the JDBC driver does not support * this data type * @see #getParams - * @since 1.4 */ public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException{ @@ -3751,7 +3733,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setObject(String parameterName, Object x) throws SQLException{ throw new SQLFeatureNotSupportedException("Feature not supported"); @@ -4024,7 +4005,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setDate(String parameterName, java.sql.Date x) throws SQLException { @@ -4050,7 +4030,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setDate(String parameterName, java.sql.Date x, Calendar cal) throws SQLException { @@ -4069,7 +4048,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setTime(String parameterName, java.sql.Time x) throws SQLException { @@ -4095,7 +4073,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setTime(String parameterName, java.sql.Time x, Calendar cal) throws SQLException { @@ -4121,7 +4098,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method * @see #getParams - * @since 1.4 */ public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal) throws SQLException { @@ -4459,7 +4435,6 @@ public abstract class BaseRowSet implements Serializable, Cloneable { * @exception SQLException if a database access error occurs or * this method is called on a closed PreparedStatement * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method - * @since 1.4 */ public void setURL(int parameterIndex, java.net.URL x) throws SQLException { throw new SQLFeatureNotSupportedException("Feature not supported"); diff --git a/jdk/src/java.sql/share/classes/javax/sql/CommonDataSource.java b/jdk/src/java.sql/share/classes/javax/sql/CommonDataSource.java index 006560cbe38..160c432474d 100644 --- a/jdk/src/java.sql/share/classes/javax/sql/CommonDataSource.java +++ b/jdk/src/java.sql/share/classes/javax/sql/CommonDataSource.java @@ -57,7 +57,6 @@ public interface CommonDataSource { * logging is disabled * @exception java.sql.SQLException if a database access error occurs * @see #setLogWriter - * @since 1.4 */ java.io.PrintWriter getLogWriter() throws SQLException; @@ -79,7 +78,6 @@ public interface CommonDataSource { * @param out the new log writer; to disable logging, set to null * @exception SQLException if a database access error occurs * @see #getLogWriter - * @since 1.4 */ void setLogWriter(java.io.PrintWriter out) throws SQLException; @@ -94,7 +92,6 @@ public interface CommonDataSource { * @param seconds the data source login time limit * @exception SQLException if a database access error occurs. * @see #getLoginTimeout - * @since 1.4 */ void setLoginTimeout(int seconds) throws SQLException; @@ -109,7 +106,6 @@ public interface CommonDataSource { * @return the data source login time limit * @exception SQLException if a database access error occurs. * @see #setLoginTimeout - * @since 1.4 */ int getLoginTimeout() throws SQLException; diff --git a/jdk/src/java.sql/share/classes/javax/sql/ConnectionPoolDataSource.java b/jdk/src/java.sql/share/classes/javax/sql/ConnectionPoolDataSource.java index 08ae5611a31..54a97b184c9 100644 --- a/jdk/src/java.sql/share/classes/javax/sql/ConnectionPoolDataSource.java +++ b/jdk/src/java.sql/share/classes/javax/sql/ConnectionPoolDataSource.java @@ -72,6 +72,34 @@ public interface ConnectionPoolDataSource extends CommonDataSource { PooledConnection getPooledConnection(String user, String password) throws SQLException; + /** + * {@inheritDoc} + * @since 1.4 + */ + @Override + java.io.PrintWriter getLogWriter() throws SQLException; + + /** + * {@inheritDoc} + * @since 1.4 + */ + @Override + void setLogWriter(java.io.PrintWriter out) throws SQLException; + + /** + * {@inheritDoc} + * @since 1.4 + */ + @Override + void setLoginTimeout(int seconds) throws SQLException; + + /** + * {@inheritDoc} + * @since 1.4 + */ + @Override + int getLoginTimeout() throws SQLException; + //------------------------- JDBC 4.3 ----------------------------------- /** diff --git a/jdk/src/java.sql/share/classes/javax/sql/DataSource.java b/jdk/src/java.sql/share/classes/javax/sql/DataSource.java index 4c3274d22d9..276a6051fe8 100644 --- a/jdk/src/java.sql/share/classes/javax/sql/DataSource.java +++ b/jdk/src/java.sql/share/classes/javax/sql/DataSource.java @@ -109,6 +109,34 @@ public interface DataSource extends CommonDataSource, Wrapper { Connection getConnection(String username, String password) throws SQLException; + /** + * {@inheritDoc} + * @since 1.4 + */ + @Override + java.io.PrintWriter getLogWriter() throws SQLException; + + /** + * {@inheritDoc} + * @since 1.4 + */ + @Override + void setLogWriter(java.io.PrintWriter out) throws SQLException; + + /** + * {@inheritDoc} + * @since 1.4 + */ + @Override + void setLoginTimeout(int seconds) throws SQLException; + + /** + * {@inheritDoc} + * @since 1.4 + */ + @Override + int getLoginTimeout() throws SQLException; + // JDBC 4.3 /** diff --git a/jdk/src/java.sql/share/classes/javax/sql/XADataSource.java b/jdk/src/java.sql/share/classes/javax/sql/XADataSource.java index 83656b205c8..0882a7de9e3 100644 --- a/jdk/src/java.sql/share/classes/javax/sql/XADataSource.java +++ b/jdk/src/java.sql/share/classes/javax/sql/XADataSource.java @@ -81,7 +81,35 @@ public interface XADataSource extends CommonDataSource { XAConnection getXAConnection(String user, String password) throws SQLException; - // JDBC 4.3 + /** + * {@inheritDoc} + * @since 1.4 + */ + @Override + java.io.PrintWriter getLogWriter() throws SQLException; + + /** + * {@inheritDoc} + * @since 1.4 + */ + @Override + void setLogWriter(java.io.PrintWriter out) throws SQLException; + + /** + * {@inheritDoc} + * @since 1.4 + */ + @Override + void setLoginTimeout(int seconds) throws SQLException; + + /** + * {@inheritDoc} + * @since 1.4 + */ + @Override + int getLoginTimeout() throws SQLException; + + // JDBC 4.3 /** * Creates a new {@code XAConnectionBuilder} instance From 59716983202233ee2342826c60d13c1553f3f1a6 Mon Sep 17 00:00:00 2001 From: Artem Smotrakov Date: Tue, 23 Aug 2016 10:32:14 -0700 Subject: [PATCH 09/51] 8164592: java/net/MulticastSocket/NoLoopbackPackets.java tests may leave a daemon thread Reviewed-by: clanger, chegar --- .../net/MulticastSocket/NoLoopbackPackets.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/jdk/test/java/net/MulticastSocket/NoLoopbackPackets.java b/jdk/test/java/net/MulticastSocket/NoLoopbackPackets.java index f01993ab131..7f7fb776df3 100644 --- a/jdk/test/java/net/MulticastSocket/NoLoopbackPackets.java +++ b/jdk/test/java/net/MulticastSocket/NoLoopbackPackets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,6 +68,7 @@ public class NoLoopbackPackets { MulticastSocket msock = null; List failedGroups = new ArrayList(); + Sender sender = null; try { msock = new MulticastSocket(); int port = msock.getLocalPort(); @@ -80,9 +81,8 @@ public class NoLoopbackPackets { groups.add(new InetSocketAddress(InetAddress.getByName("::ffff:224.1.1.2"), port)); groups.add(new InetSocketAddress(InetAddress.getByName("ff02::1:1"), port)); - Thread sender = new Thread(new Sender(groups)); - sender.setDaemon(true); // we want sender to stop when main thread exits - sender.start(); + sender = new Sender(groups); + new Thread(sender).start(); // Now try to receive multicast packets. we should not see any of them // since we disable loopback mode. @@ -107,6 +107,9 @@ public class NoLoopbackPackets { } } finally { if (msock != null) try { msock.close(); } catch (Exception e) {} + if (sender != null) { + sender.stop(); + } } if (failedGroups.size() > 0) { @@ -119,6 +122,7 @@ public class NoLoopbackPackets { static class Sender implements Runnable { private List sendToGroups; + private volatile boolean stop; public Sender(List groups) { sendToGroups = groups; @@ -136,7 +140,7 @@ public class NoLoopbackPackets { MulticastSocket msock = new MulticastSocket(); msock.setLoopbackMode(true); // disable loopback mode - for (;;) { + while (!stop) { for (DatagramPacket packet : packets) { msock.send(packet); } @@ -147,5 +151,9 @@ public class NoLoopbackPackets { throw new RuntimeException(e); } } + + void stop() { + stop = true; + } } } From 4b68f37bfedbe96e363b7a8aa8d7423dd4c5e0fa Mon Sep 17 00:00:00 2001 From: Artem Smotrakov Date: Tue, 23 Aug 2016 10:38:01 -0700 Subject: [PATCH 10/51] 8164159: java/nio/file/WatchService/UpdateInterference.java test leaves daemon threads Reviewed-by: alanb --- .../file/WatchService/UpdateInterference.java | 134 +++++++++++------- 1 file changed, 81 insertions(+), 53 deletions(-) diff --git a/jdk/test/java/nio/file/WatchService/UpdateInterference.java b/jdk/test/java/nio/file/WatchService/UpdateInterference.java index 5bd88121795..93219d18edb 100644 --- a/jdk/test/java/nio/file/WatchService/UpdateInterference.java +++ b/jdk/test/java/nio/file/WatchService/UpdateInterference.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,9 @@ import java.util.concurrent.TimeUnit; import static java.nio.file.StandardWatchEventKinds.*; public class UpdateInterference { + + private static volatile boolean stop; + public static void main(String[] args) throws IOException, InterruptedException { final Path root = Files.createTempDirectory("test"); final Path foo = root.resolve("foo"); @@ -43,64 +46,89 @@ public class UpdateInterference { Files.createDirectory(bar); Files.createDirectory(baz); - final WatchService watcher = root.getFileSystem().newWatchService(); - final WatchKey fooKey = foo.register(watcher, ENTRY_CREATE); - final WatchKey barKey = bar.register(watcher, ENTRY_CREATE); + try (final WatchService watcher = root.getFileSystem().newWatchService()) { + final WatchKey fooKey = foo.register(watcher, ENTRY_CREATE); + final WatchKey barKey = bar.register(watcher, ENTRY_CREATE); - new Thread() { - { setDaemon(true); } + Thread t1 = null; + Thread t2 = null; + try { + t1 = new Thread() { - @Override - public void run() { - while (true) { - try { - final Path temp = Files.createTempFile(foo, "temp", ".tmp"); - Files.delete(temp); - Thread.sleep(10); - } catch (IOException | InterruptedException e) { - throw new RuntimeException(e); - } - } - } - }.start(); - - new Thread() { - { setDaemon(true); } - - @Override - public void run() { - WatchKey bazKeys[] = new WatchKey[32]; - while (true) { - try { - for( int i = 0; i < bazKeys.length; i++) { - bazKeys[i] = baz.register(watcher, ENTRY_CREATE); + @Override + public void run() { + while (!stop) { + try { + final Path temp = Files.createTempFile(foo, "temp", ".tmp"); + Files.delete(temp); + Thread.sleep(10); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } } - for( int i = 0; i < bazKeys.length; i++) { - bazKeys[i].cancel(); - } - Thread.sleep(1); - } catch (IOException | InterruptedException e) { - throw new RuntimeException(e); } + }; + + t2 = new Thread() { + + @Override + public void run() { + WatchKey bazKeys[] = new WatchKey[32]; + while (!stop) { + try { + for( int i = 0; i < bazKeys.length; i++) { + bazKeys[i] = baz.register(watcher, ENTRY_CREATE); + } + for( int i = 0; i < bazKeys.length; i++) { + bazKeys[i].cancel(); + } + Thread.sleep(1); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + } + } + }; + + t1.start(); + t2.start(); + + long time = System.currentTimeMillis(); + while ((System.currentTimeMillis() - time) < 15000) { + final WatchKey key = watcher.poll(60, TimeUnit.SECONDS); + if (key == null) continue; + + if (key != fooKey) { + List> pollEvents = key.pollEvents(); + for (WatchEvent watchEvent : pollEvents) { + System.out.println(watchEvent.count() + " " + + watchEvent.kind() + " " + + watchEvent.context()); + } + throw new RuntimeException("Event received for unexpected key"); + } + key.reset(); + } + } finally { + // the threads should stop before WatchService is closed + // to avoid ClosedWatchServiceException + stop = true; + + // wait for threads to finish + if (t1 != null) { + t1.join(); + } + + if (t2 != null) { + t2.join(); } } - }.start(); - - long time = System.currentTimeMillis(); - while ((System.currentTimeMillis() - time) < 15000) { - final WatchKey key = watcher.poll(60, TimeUnit.SECONDS); - if (key == null) continue; - - if (key != fooKey) { - List> pollEvents = key.pollEvents(); - for (WatchEvent watchEvent : pollEvents) { - System.out.println(watchEvent.count() + " " + - watchEvent.kind() + " " + - watchEvent.context()); - } - throw new RuntimeException("Event received for unexpected key"); - } - key.reset(); + } finally { + // clean up + Files.delete(foo); + Files.delete(bar); + Files.delete(baz); + Files.delete(root); } } } From 496a6f67d640bda110ea13431a0136dad5bf98fe Mon Sep 17 00:00:00 2001 From: Brent Christian Date: Tue, 23 Aug 2016 10:49:15 -0700 Subject: [PATCH 11/51] 7180225: SecurityExceptions not defined in some class loader methods Reviewed-by: mchung, mullan --- .../share/classes/java/lang/Class.java | 28 +++++------- .../share/classes/java/lang/ClassLoader.java | 43 ++++++------------- .../share/classes/java/lang/Thread.java | 21 ++++----- 3 files changed, 32 insertions(+), 60 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/Class.java b/jdk/src/java.base/share/classes/java/lang/Class.java index 25d4a3b5b9f..8c9957274d6 100644 --- a/jdk/src/java.base/share/classes/java/lang/Class.java +++ b/jdk/src/java.base/share/classes/java/lang/Class.java @@ -331,12 +331,6 @@ public final class Class implements java.io.Serializable, * Note that this method does not check whether the requested class * is accessible to its caller. * - *

    If the {@code loader} is {@code null}, and a security - * manager is present, and the caller's class loader is not null, then this - * method calls the security manager's {@code checkPermission} method - * with a {@code RuntimePermission("getClassLoader")} permission to - * ensure it's ok to access the bootstrap class loader. - * * @param name fully qualified name of the desired class * @param initialize if {@code true} the class will be initialized. * See Section 12.4 of The Java Language Specification. @@ -348,6 +342,11 @@ public final class Class implements java.io.Serializable, * by this method fails * @exception ClassNotFoundException if the class cannot be located by * the specified class loader + * @exception SecurityException + * if a security manager is present, and the {@code loader} is + * {@code null}, and the caller's class loader is not + * {@code null}, and the caller does not have the + * {@link RuntimePermission}{@code ("getClassLoader")} * * @see java.lang.Class#forName(String) * @see java.lang.ClassLoader @@ -782,22 +781,17 @@ public final class Class implements java.io.Serializable, * null in such implementations if this class was loaded by the bootstrap * class loader. * - *

    If a security manager is present, and the caller's class loader is - * not null and the caller's class loader is not the same as or an ancestor of - * the class loader for the class whose class loader is requested, then - * this method calls the security manager's {@code checkPermission} - * method with a {@code RuntimePermission("getClassLoader")} - * permission to ensure it's ok to access the class loader for the class. - * *

    If this object * represents a primitive type or void, null is returned. * * @return the class loader that loaded the class or interface * represented by this object. - * @throws SecurityException - * if a security manager exists and its - * {@code checkPermission} method denies - * access to the class loader for the class. + * @throws SecurityException + * if a security manager is present, and the caller's class loader + * is not {@code null} and is not the same as or an ancestor of the + * class loader for the class whose class loader is requested, + * and the caller does not have the + * {@link RuntimePermission}{@code ("getClassLoader")} * @see java.lang.ClassLoader * @see SecurityManager#checkPermission * @see java.lang.RuntimePermission diff --git a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java index 013912384d8..d8b2dee337d 100644 --- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java @@ -1537,22 +1537,13 @@ public abstract class ClassLoader { * will return null in such implementations if this class loader's * parent is the bootstrap class loader. * - *

    If a security manager is present, and the invoker's class loader is - * not null and is not an ancestor of this class loader, then this - * method invokes the security manager's {@link - * SecurityManager#checkPermission(java.security.Permission) - * checkPermission} method with a {@link - * RuntimePermission#RuntimePermission(String) - * RuntimePermission("getClassLoader")} permission to verify - * access to the parent class loader is permitted. If not, a - * SecurityException will be thrown.

    - * * @return The parent ClassLoader * * @throws SecurityException - * If a security manager exists and its checkPermission - * method doesn't allow access to this class loader's parent class - * loader. + * If a security manager is present, and the caller's class loader + * is not {@code null} and is not an ancestor of this class loader, + * and the caller does not have the + * {@link RuntimePermission}{@code ("getClassLoader")} * * @since 1.2 */ @@ -1590,12 +1581,11 @@ public abstract class ClassLoader { * @return The platform {@code ClassLoader}. * * @throws SecurityException - * If a security manager exists and the caller's class loader is - * not {@code null} and the caller's class loader is not the same + * If a security manager is present, and the caller's class loader is + * not {@code null}, and the caller's class loader is not the same * as or an ancestor of the platform class loader, - * and the {@link SecurityManager#checkPermission(java.security.Permission) - * checkPermission} method denies {@code RuntimePermission("getClassLoader")} - * to access the platform class loader. + * and the caller does not have the + * {@link RuntimePermission}{@code ("getClassLoader")} * * @since 9 */ @@ -1636,17 +1626,6 @@ public abstract class ClassLoader { * If circular initialization of the system class loader is detected then * an unspecified error or exception is thrown. * - *

    If a security manager is present, and the invoker's class loader is - * not null and the invoker's class loader is not the same as or - * an ancestor of the system class loader, then this method invokes the - * security manager's {@link - * SecurityManager#checkPermission(java.security.Permission) - * checkPermission} method with a {@link - * RuntimePermission#RuntimePermission(String) - * RuntimePermission("getClassLoader")} permission to verify - * access to the system class loader. If not, a - * SecurityException will be thrown.

    - * * @implNote The system property to override the system class loader is not * examined until the VM is almost fully initialized. Code that executes * this method during startup should take care not to cache the return @@ -1656,8 +1635,10 @@ public abstract class ClassLoader { * null if none * * @throws SecurityException - * If a security manager exists and its checkPermission - * method doesn't allow access to the system class loader. + * If a security manager is present, and the caller's class loader + * is not {@code null} and is not the same as or an ancestor of the + * system class loader, and the caller does not have the + * {@link RuntimePermission}{@code ("getClassLoader")} * * @throws IllegalStateException * If invoked recursively during the construction of the class diff --git a/jdk/src/java.base/share/classes/java/lang/Thread.java b/jdk/src/java.base/share/classes/java/lang/Thread.java index 310ada1b470..4fac9eddf07 100644 --- a/jdk/src/java.base/share/classes/java/lang/Thread.java +++ b/jdk/src/java.base/share/classes/java/lang/Thread.java @@ -1507,28 +1507,25 @@ class Thread implements Runnable { } /** - * Returns the context ClassLoader for this Thread. The context - * ClassLoader is provided by the creator of the thread for use + * Returns the context {@code ClassLoader} for this thread. The context + * {@code ClassLoader} is provided by the creator of the thread for use * by code running in this thread when loading classes and resources. * If not {@linkplain #setContextClassLoader set}, the default is the - * ClassLoader context of the parent Thread. The context ClassLoader of the + * {@code ClassLoader} context of the parent thread. The context + * {@code ClassLoader} of the * primordial thread is typically set to the class loader used to load the * application. * - *

    If a security manager is present, and the invoker's class loader is not - * {@code null} and is not the same as or an ancestor of the context class - * loader, then this method invokes the security manager's {@link - * SecurityManager#checkPermission(java.security.Permission) checkPermission} - * method with a {@link RuntimePermission RuntimePermission}{@code - * ("getClassLoader")} permission to verify that retrieval of the context - * class loader is permitted. * - * @return the context ClassLoader for this Thread, or {@code null} + * @return the context {@code ClassLoader} for this thread, or {@code null} * indicating the system class loader (or, failing that, the * bootstrap class loader) * * @throws SecurityException - * if the current thread cannot get the context ClassLoader + * if a security manager is present, and the caller's class loader + * is not {@code null} and is not the same as or an ancestor of the + * context class loader, and the caller does not have the + * {@link RuntimePermission}{@code ("getClassLoader")} * * @since 1.2 */ From dc3e5ed9fb92be3c93b827333477aa0e7901251a Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Tue, 23 Aug 2016 10:51:17 -0700 Subject: [PATCH 12/51] 8164556: Drop AAC and FLAC from content type check in java/nio/file/Files/probeContentType/Basic.java Remove file extensions of AAC and FLAC audio encodings from the list of extensions verified. Reviewed-by: alanb --- .../file/Files/probeContentType/Basic.java | 45 +++++-------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/jdk/test/java/nio/file/Files/probeContentType/Basic.java b/jdk/test/java/nio/file/Files/probeContentType/Basic.java index 003f9494f11..9786c701451 100644 --- a/jdk/test/java/nio/file/Files/probeContentType/Basic.java +++ b/jdk/test/java/nio/file/Files/probeContentType/Basic.java @@ -95,7 +95,7 @@ public class Basic { return 0; } - static int checkContentTypes(String[] extensions, String[][] expectedTypes) + static int checkContentTypes(String[] extensions, String[] expectedTypes) throws IOException { if (extensions.length != expectedTypes.length) { System.err.println("Parameter array lengths differ"); @@ -112,27 +112,10 @@ public class Basic { System.err.println("Content type of " + extension + " cannot be determined"); failures++; - } else { - boolean isTypeFound = false; - for (String s : expectedTypes[i]) { - if (type.equals(s)) { - isTypeFound = true; - break; - } - } - if (!isTypeFound) { - System.err.printf("Content type: %s; expected: ", type); - int j = 0; - for (String s : expectedTypes[i]) { - if (j++ == 0) { - System.err.printf("%s", s); - } else { - System.err.printf(", or %s", s); - } - } - System.err.println(); - failures++; - } + } else if (!type.equals(expectedTypes[i])) { + System.err.printf("Content type: %s; expected: %s%n", + type, expectedTypes); + failures++; } } finally { Files.delete(file); @@ -174,8 +157,6 @@ public class Basic { // Verify that certain media extensions are mapped to the correct type. String[] extensions = new String[]{ - "aac", - "flac", "jpg", "mp3", "mp4", @@ -183,15 +164,13 @@ public class Basic { "png", "webm" }; - String[][] expectedTypes = new String[][] { - {"audio/aac", "audio/x-aac", "audio/vnd.dlna.adts"}, - {"audio/flac", "audio/x-flac"}, - {"image/jpeg"}, - {"audio/mpeg"}, - {"video/mp4"}, - {"application/pdf"}, - {"image/png"}, - {"video/webm"} + String[] expectedTypes = new String[] { + "image/jpeg", + "audio/mpeg", + "video/mp4", + "application/pdf", + "image/png", + "video/webm" }; failures += checkContentTypes(extensions, expectedTypes); From f3e6d78c818d69c5f7dee07631a38bd1a3acc7dd Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Tue, 23 Aug 2016 15:44:01 -0700 Subject: [PATCH 13/51] 8160971: Re-enable VarHandle tests quarantined by JDK-8160690 Reviewed-by: vlivanov --- jdk/test/ProblemList.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 5bad9db84d4..2165bef4aba 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -124,10 +124,6 @@ java/beans/Introspector/8132566/OverrideUserDefPropertyInfoTest.java 8132565 gen # jdk_lang java/lang/StringCoding/CheckEncodings.sh 7008363 generic-all -java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java 8160690 generic-all -java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java 8160690 generic-all -java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java 8160690 generic-all -java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java 8160690 generic-all ############################################################################ From 3a04923cadc5cd8be9cb6827806fae8926d5c852 Mon Sep 17 00:00:00 2001 From: Steve Drach Date: Tue, 23 Aug 2016 11:26:41 -0700 Subject: [PATCH 14/51] 8164585: JarFile::isMultiRelease does not return true in all cases where it should return true Reviewed-by: alanb, psandoz --- jdk/src/java.base/share/classes/java/util/jar/JarFile.java | 6 +++--- .../java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java index 82a96607b90..2c4500d169b 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java @@ -353,7 +353,7 @@ class JarFile extends ZipFile { if (isMultiRelease) { return true; } - if (MULTI_RELEASE_ENABLED && versionMajor != BASE_VERSION_MAJOR) { + if (MULTI_RELEASE_ENABLED) { try { checkForSpecialAttributes(); } catch (IOException io) { @@ -644,7 +644,7 @@ class JarFile extends ZipFile { return signers == null ? null : signers.clone(); } JarFileEntry realEntry() { - if (isMultiRelease()) { + if (isMultiRelease() && versionMajor != BASE_VERSION_MAJOR) { String entryName = super.getName(); return entryName.equals(this.name) ? this : new JarFileEntry(entryName, this); } @@ -960,7 +960,7 @@ class JarFile extends ZipFile { hasClassPathAttribute = match(CLASSPATH_CHARS, b, CLASSPATH_LASTOCC) != -1; // is this a multi-release jar file - if (MULTI_RELEASE_ENABLED && versionMajor != BASE_VERSION_MAJOR) { + if (MULTI_RELEASE_ENABLED) { int i = match(MULTIRELEASE_CHARS, b, MULTIRELEASE_LASTOCC); if (i != -1) { i += MULTIRELEASE_CHARS.length; diff --git a/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java index bae8265be67..4ea94150844 100644 --- a/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java +++ b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java @@ -80,7 +80,7 @@ public class MultiReleaseJarAPI { } try (JarFile jf = new JarFile(multirelease)) { - Assert.assertFalse(jf.isMultiRelease()); + Assert.assertTrue(jf.isMultiRelease()); } try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Runtime.version())) { From dfa00059e299c20673b16a08d5df3a483b8a5b69 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Wed, 24 Aug 2016 13:32:00 +0800 Subject: [PATCH 15/51] 8164656: krb5 does not retry if TCP connection timeouts Reviewed-by: xuelei --- .../classes/sun/security/krb5/KdcComm.java | 38 +- .../sun/security/krb5/auto/KdcPolicy.java | 366 ++++++++++++++++++ 2 files changed, 381 insertions(+), 23 deletions(-) create mode 100644 jdk/test/sun/security/krb5/auto/KdcPolicy.java diff --git a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java index 721c105d345..a4dbf2903bb 100644 --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java @@ -390,35 +390,27 @@ public final class KdcComm { for (int i=1; i <= retries; i++) { String proto = useTCP?"TCP":"UDP"; - try (NetClient kdcClient = NetClient.getInstance( - proto, kdc, port, timeout)) { - if (DEBUG) { - System.out.println(">>> KDCCommunication: kdc=" + kdc + if (DEBUG) { + System.out.println(">>> KDCCommunication: kdc=" + kdc + " " + proto + ":" + port + ", timeout=" + timeout + ",Attempt =" + i + ", #bytes=" + obuf.length); + } + try (NetClient kdcClient = NetClient.getInstance( + proto, kdc, port, timeout)) { + kdcClient.send(obuf); + ibuf = kdcClient.receive(); + break; + } catch (SocketTimeoutException se) { + if (DEBUG) { + System.out.println ("SocketTimeOutException with " + + "attempt: " + i); } - try { - /* - * Send the data to the kdc. - */ - kdcClient.send(obuf); - /* - * And get a response. - */ - ibuf = kdcClient.receive(); - break; - } catch (SocketTimeoutException se) { - if (DEBUG) { - System.out.println ("SocketTimeOutException with " + - "attempt: " + i); - } - if (i == retries) { - ibuf = null; - throw se; - } + if (i == retries) { + ibuf = null; + throw se; } } } diff --git a/jdk/test/sun/security/krb5/auto/KdcPolicy.java b/jdk/test/sun/security/krb5/auto/KdcPolicy.java new file mode 100644 index 00000000000..f4501a5779b --- /dev/null +++ b/jdk/test/sun/security/krb5/auto/KdcPolicy.java @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.*; +import java.net.DatagramSocket; +import java.net.ServerSocket; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.Security; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.security.auth.login.LoginException; +import sun.security.krb5.Asn1Exception; +import sun.security.krb5.Config; + +/* + * @test + * @bug 8164656 + * @run main/othervm KdcPolicy udp + * @run main/othervm KdcPolicy tcp + * @summary krb5.kdc.bad.policy test + */ +public class KdcPolicy { + + // Is this test on UDP? + static boolean udp; + + public static void main(String[] args) throws Exception { + + udp = args[0].equals("udp"); + + try { + main0(); + } catch (LoginException le) { + Throwable cause = le.getCause(); + if (cause instanceof Asn1Exception) { + System.out.println("Another process sends a packet to " + + "this server. Ignored."); + return; + } + throw le; + } + } + + static DebugMatcher cm = new DebugMatcher(); + + static void main0() throws Exception { + + System.setProperty("sun.security.krb5.debug", "true"); + + // One real KDC. Must be created before fake KDCs + // to read the TestHosts file. + OneKDC kdc = new OneKDC(null); + + // Two fake KDCs, d1 and d2 only listen but do not respond. + + if (udp) { + try (DatagramSocket d1 = new DatagramSocket(); + DatagramSocket d2 = new DatagramSocket()) { + run(d1.getLocalPort(), d2.getLocalPort(), kdc.getPort()); + } + } else { + try (ServerSocket d1 = new ServerSocket(0); + ServerSocket d2 = new ServerSocket(0)) { + run(d1.getLocalPort(), d2.getLocalPort(), kdc.getPort()); + } + } + } + + static void run(int p1, int p2, int p3) throws Exception { + + // cm.kdc() will return a and b for fake KDCs, and c for real KDC. + cm.addPort(-1).addPort(p1).addPort(p2).addPort(p3); + + System.setProperty("java.security.krb5.conf", "alternative-krb5.conf"); + + // Check default timeout is 30s. Use real KDC only, otherwise too + // slow to wait for timeout. + writeConf(-1, -1, p3); + test("c30000c30000"); + + // 1. Default policy is tryLast + //Security.setProperty("krb5.kdc.bad.policy", "tryLast"); + + // Need a real KDC, otherwise there is no last good. + // This test waste 3 seconds waiting for d1 to timeout. + // It is possible the real KDC cannot fulfil the request + // in 3s, so it might fail (either 1st time or 2nd time). + writeConf(1, 3000, p1, p3); + test("a3000c3000c3000|a3000c3000-|a3000c3000c3000-"); + + // If a test case won't use a real KDC, it can be sped up. + writeConf(3, 5, p1, p2); + test("a5a5a5b5b5b5-"); // default max_retries == 3 + test("a5a5a5b5b5b5-"); // all bad means no bad + + // 2. No policy. + Security.setProperty("krb5.kdc.bad.policy", ""); + Config.refresh(); + + // This case needs a real KDC, otherwise, all bad means no + // bad and we cannot tell the difference. This case waste 3 + // seconds on d1 to timeout twice. It is possible the real KDC + // cannot fulfil the request within 3s, so it might fail + // (either 1st time or 2nd time). + writeConf(1, 3000, p1, p3); + test("a3000c3000a3000c3000|a3000c3000-|a3000c3000a3000c3000-"); + + // 3. tryLess with no argument means tryLess:1,5000 + Security.setProperty("krb5.kdc.bad.policy", "tryLess"); + + // This case will waste 11s. We are checking that the default + // value of 5000 in tryLess is only used if it's less than timeout + // in krb5.conf + writeConf(1, 6000, p1); + test("a6000-"); // timeout in krb5.conf is 6s + test("a5000-"); // tryLess to 5s. This line can be made faster if + // d1 is a read KDC, but we have no existing method + // to start KDC on an existing ServerSocket (port). + + writeConf(-1, 4, p1, p2); + test("a4a4a4b4b4b4-"); // default max_retries == 3 + test("a4b4-"); // tryLess to 1. And since 4 < 5000, use 4. + Config.refresh(); + test("a4a4a4b4b4b4-"); + + writeConf(5, 4, p1, p2); + test("a4a4a4a4a4b4b4b4b4b4-"); // user-provided max_retries == 5 + test("a4b4-"); + Config.refresh(); + test("a4a4a4a4a4b4b4b4b4b4-"); + + // 3. tryLess with arguments + Security.setProperty("krb5.kdc.bad.policy", + "tryLess:2,5"); + + writeConf(-1, 6, p1, p2); + test("a6a6a6b6b6b6-"); // default max_retries == 3 + test("a5a5b5b5-"); // tryLess to 2 + Config.refresh(); + test("a6a6a6b6b6b6-"); + + writeConf(5, 4, p1, p2); + test("a4a4a4a4a4b4b4b4b4b4-"); // user-provided max_retries == 5 + test("a4a4b4b4-"); // tryLess to 2 + Config.refresh(); + test("a4a4a4a4a4b4b4b4b4b4-"); + } + + /** + * Writes a krb5.conf file. + * @param max max_retries, -1 if not set + * @param to kdc_timeout, -1 if not set + * @param ports where KDCs listen on + */ + static void writeConf(int max, int to, int... ports) throws Exception { + + // content of krb5.conf + String conf = ""; + + // Extra settings in [libdefaults] + String inDefaults = ""; + + // Extra settings in [realms] + String inRealm = ""; + + // We will randomly put extra settings only in [libdefaults], + // or in [realms] but with different values in [libdefaults], + // to prove that settings in [realms] override those in [libdefaults]. + Random r = new Random(); + + if (max > 0) { + if (r.nextBoolean()) { + inDefaults += "max_retries = " + max + "\n"; + } else { + inRealm += " max_retries = " + max + "\n"; + inDefaults += "max_retries = " + (max + 1) + "\n"; + } + } + + if (to > 0) { + if (r.nextBoolean()) { + inDefaults += "kdc_timeout = " + to + "\n"; + } else { + inRealm += " kdc_timeout = " + to + "\n"; + inDefaults += "kdc_timeout = " + (to + 1) + "\n"; + } + } + + if (udp) { + if (r.nextBoolean()) { + inDefaults += "udp_preference_limit = 10000\n"; + } else if (r.nextBoolean()) { + inRealm += " udp_preference_limit = 10000\n"; + inDefaults += "udp_preference_limit = 1\n"; + } // else no settings means UDP + } else { + if (r.nextBoolean()) { + inDefaults += "udp_preference_limit = 1\n"; + } else { + inRealm += " udp_preference_limit = 1\n"; + inDefaults += "udp_preference_limit = 10000\n"; + } + } + + conf = "[libdefaults]\n" + + "default_realm = " + OneKDC.REALM + "\n" + + inDefaults + + "\n" + + "[realms]\n" + + OneKDC.REALM + " = {\n"; + + for (int port : ports) { + conf += " kdc = " + OneKDC.KDCHOST + ":" + port + "\n" + + inRealm; + } + + conf += "}\n"; + + Files.write(Paths.get("alternative-krb5.conf"), conf.getBytes()); + Config.refresh(); + } + + /** + * One call of krb5 login. As long as the result matches one of expected, + * the test is considered as success. The grammar of expected is + * + * kdc#, timeout, kdc#, timeout, ..., optional "-" for failure + */ + static void test(String... expected) throws Exception { + + System.out.println("------------------TEST----------------------"); + PrintStream oldOut = System.out; + boolean failed = false; + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bo)); + try { + Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false); + } catch (Exception e) { + failed = true; + } finally { + System.setOut(oldOut); + } + + String[] lines = new String(bo.toByteArray()).split("\n"); + StringBuilder sb = new StringBuilder(); + for (String line: lines) { + if (cm.match(line)) { + if (udp != cm.isUDP()) { + sb.append("x"); + } + sb.append(cm.kdc()).append(cm.timeout()); + } + } + if (failed) sb.append('-'); + + String output = sb.toString(); + + boolean found = false; + for (String ex : expected) { + if (output.matches(ex)) { + System.out.println("Expected: " + ex + ", actual " + output); + found = true; + break; + } + } + + if (!found) { + System.out.println("--------------- ERROR START -------------"); + System.out.println(new String(bo.toByteArray())); + System.out.println("--------------- ERROR END ---------------"); + throw new Exception("Does not match. Output is " + output); + } + } + + /** + * A helper class to match the krb5 debug output: + * >>> KDCCommunication: kdc=host UDP:11555, timeout=200,Attempt =1, #bytes=138 + * + * Example: + * DebugMatcher cm = new DebugMatcher(); + * cm.addPort(12345).addPort(11555); + * for (String line : debugOutput) { + * if (cm.match(line)) { + * System.out.printf("%c%d\n", cm.kdc(), cm.timeout()); + * // shows b200 for the example above + * } + * } + */ + static class DebugMatcher { + + static final Pattern re = Pattern.compile( + ">>> KDCCommunication: kdc=\\S+ (TCP|UDP):(\\d+), " + + "timeout=(\\d+),Attempt\\s*=(\\d+)"); + + List kdcPorts = new ArrayList<>(); + Matcher matcher; + + /** + * Add KDC ports one by one. See {@link #kdc()}. + */ + DebugMatcher addPort(int port) { + if (port > 0) { + kdcPorts.add(port); + } else { + kdcPorts.clear(); + } + return this; + } + + /** + * When a line matches the ">>> KDCCommunication:" pattern. After a + * match, the getters below can be called on this match. + */ + boolean match(String line) { + matcher = re.matcher(line); + return matcher.find(); + } + + /** + * Protocol of this match, "UDP" or "TCP". + */ + boolean isUDP() { + return matcher.group(1).equals("UDP"); + } + + /** + * KDC for this match, "a" for the one 1st added bt addPort(), "b" + * for second, etc. Undefined for not added. + */ + char kdc() { + int port = Integer.parseInt(matcher.group(2)); + return (char) (kdcPorts.indexOf(port) + 'a'); + } + + /** + * Timeout value for this match. + */ + int timeout() { + return Integer.parseInt(matcher.group(3)); + } + } +} From 200608b4c00688d7bccdcb6328a627e258b8cd17 Mon Sep 17 00:00:00 2001 From: Srinivas Dama Date: Wed, 24 Aug 2016 14:02:41 +0530 Subject: [PATCH 16/51] 8164618: add documentation for NativeNumber and NativeBoolean Reviewed-by: sundar --- .../codegen/OptimisticTypesCalculator.java | 2 +- .../runtime/resources/Functions.properties | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java index ac05a5f77ca..a026f2d2c57 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java @@ -79,7 +79,7 @@ final class OptimisticTypesCalculator extends SimpleNodeVisitor { @Override public boolean enterPropertyNode(final PropertyNode propertyNode) { - if(propertyNode.getKeyName().equals(ScriptObject.PROTO_PROPERTY_NAME)) { + if(ScriptObject.PROTO_PROPERTY_NAME.equals(propertyNode.getKeyName())) { tagNeverOptimistic(propertyNode.getValue()); } return super.enterPropertyNode(propertyNode); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Functions.properties b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Functions.properties index 718f6cb07ef..d259e7528b5 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Functions.properties +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Functions.properties @@ -173,3 +173,20 @@ String.prototype.toUpperCase=returns a new string representing the calling strin String.prototype.toLocaleUpperCase=returns a new string representing the calling string value converted to upper case according to any locale specific case mappings String.prototype.trim=returns a new string representing the calling string with white space removed from both ends + +Boolean.prototype.toString=returns string representation of specified Boolean object + +Boolean.prototype.valueOf=returns the primitive value of the specified Boolean object + +Number.prototype.toString=returns string representation of specified object in the specified radix + +Number.prototype.toLocaleString=returns a string with a language sensitive representation of this number + +Number.prototype.valueOf=returns the primitive value of the specified object + +Number.prototype.toFixed=returns a string representing the number in decimal fixed-point notation + +Number.prototype.toExponential=returns a string representing the number in decimal exponential notation + +Number.prototype.toPrecision=returns a string representing the number to a specified precision in fixed-point or exponential notation + From 338343e0e154d36e45d581f8db558b96847936b4 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Wed, 24 Aug 2016 13:54:17 +0200 Subject: [PATCH 17/51] 8164669: Lazier initialization of java.time Reviewed-by: scolebourne, chegar, alanb --- .../java.base/share/classes/java/time/Duration.java | 6 ++++-- .../share/classes/sun/util/calendar/ZoneInfo.java | 10 +--------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/time/Duration.java b/jdk/src/java.base/share/classes/java/time/Duration.java index 13e8eff9783..e2c55a971ea 100644 --- a/jdk/src/java.base/share/classes/java/time/Duration.java +++ b/jdk/src/java.base/share/classes/java/time/Duration.java @@ -150,10 +150,12 @@ public final class Duration /** * The pattern for parsing. */ - private static final Pattern PATTERN = + private static class Lazy { + static final Pattern PATTERN = Pattern.compile("([-+]?)P(?:([-+]?[0-9]+)D)?" + "(T(?:([-+]?[0-9]+)H)?(?:([-+]?[0-9]+)M)?(?:([-+]?[0-9]+)(?:[.,]([0-9]{0,9}))?S)?)?", Pattern.CASE_INSENSITIVE); + } /** * The number of seconds in the duration. @@ -387,7 +389,7 @@ public final class Duration */ public static Duration parse(CharSequence text) { Objects.requireNonNull(text, "text"); - Matcher matcher = PATTERN.matcher(text); + Matcher matcher = Lazy.PATTERN.matcher(text); if (matcher.matches()) { // check for letter T but no time sections if (!charMatch(text, matcher.start(3), matcher.end(3), 'T')) { diff --git a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfo.java b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfo.java index 98c9442be36..f3929ee389f 100644 --- a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfo.java +++ b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfo.java @@ -27,15 +27,8 @@ package sun.util.calendar; import java.io.IOException; import java.io.ObjectInputStream; -import java.lang.ref.SoftReference; -import java.security.AccessController; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Date; -import java.util.List; -import java.util.Locale; import java.util.Map; -import java.util.Set; import java.util.SimpleTimeZone; import java.util.TimeZone; @@ -80,8 +73,6 @@ public class ZoneInfo extends TimeZone { private static final long ABBR_MASK = 0xf00L; private static final int TRANSITION_NSHIFT = 12; - private static final CalendarSystem gcal = CalendarSystem.getGregorianCalendar(); - /** * The raw GMT offset in milliseconds between this zone and GMT. * Negative offsets are to the west of Greenwich. To obtain local @@ -379,6 +370,7 @@ public class ZoneInfo extends TimeZone { throw new IllegalArgumentException(); } + Gregorian gcal = CalendarSystem.getGregorianCalendar(); CalendarDate date = gcal.newCalendarDate(null); date.setDate(year, month + 1, day); if (gcal.validate(date) == false) { From 5431436909d03b8093fa21a764faffc59aa82e77 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Wed, 24 Aug 2016 16:09:34 +0200 Subject: [PATCH 18/51] 8164483: Generate field lambda forms at link time Reviewed-by: vlivanov --- .../java/lang/invoke/DirectMethodHandle.java | 97 +++++++++++++++---- .../lang/invoke/GenerateJLIClassesHelper.java | 43 ++++++-- .../lang/invoke/InvokerBytecodeGenerator.java | 18 ++++ .../classes/java/lang/invoke/LambdaForm.java | 38 +++++++- 4 files changed, 167 insertions(+), 29 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java index 174e914f805..ce1f938583f 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java @@ -492,7 +492,7 @@ class DirectMethodHandle extends MethodHandle { } // Caching machinery for field accessors: - private static final byte + static final byte AF_GETFIELD = 0, AF_PUTFIELD = 1, AF_GETSTATIC = 2, @@ -502,7 +502,7 @@ class DirectMethodHandle extends MethodHandle { AF_LIMIT = 6; // Enumerate the different field kinds using Wrapper, // with an extra case added for checked references. - private static final int + static final int FT_LAST_WRAPPER = Wrapper.COUNT-1, FT_UNCHECKED_REF = Wrapper.OBJECT.ordinal(), FT_CHECKED_REF = FT_LAST_WRAPPER+1, @@ -515,7 +515,7 @@ class DirectMethodHandle extends MethodHandle { @Stable private static final LambdaForm[] ACCESSOR_FORMS = new LambdaForm[afIndex(AF_LIMIT, false, 0)]; - private static int ftypeKind(Class ftype) { + static int ftypeKind(Class ftype) { if (ftype.isPrimitive()) return Wrapper.forPrimitiveType(ftype).ordinal(); else if (VerifyType.isNullReferenceConversion(Object.class, ftype)) @@ -566,7 +566,64 @@ class DirectMethodHandle extends MethodHandle { private static final Wrapper[] ALL_WRAPPERS = Wrapper.values(); - private static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) { + private static Kind getFieldKind(boolean isGetter, boolean isVolatile, Wrapper wrapper) { + if (isGetter) { + if (isVolatile) { + switch (wrapper) { + case BOOLEAN: return GET_BOOLEAN_VOLATILE; + case BYTE: return GET_BYTE_VOLATILE; + case SHORT: return GET_SHORT_VOLATILE; + case CHAR: return GET_CHAR_VOLATILE; + case INT: return GET_INT_VOLATILE; + case LONG: return GET_LONG_VOLATILE; + case FLOAT: return GET_FLOAT_VOLATILE; + case DOUBLE: return GET_DOUBLE_VOLATILE; + case OBJECT: return GET_OBJECT_VOLATILE; + } + } else { + switch (wrapper) { + case BOOLEAN: return GET_BOOLEAN; + case BYTE: return GET_BYTE; + case SHORT: return GET_SHORT; + case CHAR: return GET_CHAR; + case INT: return GET_INT; + case LONG: return GET_LONG; + case FLOAT: return GET_FLOAT; + case DOUBLE: return GET_DOUBLE; + case OBJECT: return GET_OBJECT; + } + } + } else { + if (isVolatile) { + switch (wrapper) { + case BOOLEAN: return PUT_BOOLEAN_VOLATILE; + case BYTE: return PUT_BYTE_VOLATILE; + case SHORT: return PUT_SHORT_VOLATILE; + case CHAR: return PUT_CHAR_VOLATILE; + case INT: return PUT_INT_VOLATILE; + case LONG: return PUT_LONG_VOLATILE; + case FLOAT: return PUT_FLOAT_VOLATILE; + case DOUBLE: return PUT_DOUBLE_VOLATILE; + case OBJECT: return PUT_OBJECT_VOLATILE; + } + } else { + switch (wrapper) { + case BOOLEAN: return PUT_BOOLEAN; + case BYTE: return PUT_BYTE; + case SHORT: return PUT_SHORT; + case CHAR: return PUT_CHAR; + case INT: return PUT_INT; + case LONG: return PUT_LONG; + case FLOAT: return PUT_FLOAT; + case DOUBLE: return PUT_DOUBLE; + case OBJECT: return PUT_OBJECT; + } + } + } + throw new AssertionError("Invalid arguments"); + } + + static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) { boolean isGetter = (formOp & 1) == (AF_GETFIELD & 1); boolean isStatic = (formOp >= AF_GETSTATIC); boolean needsInit = (formOp >= AF_GETSTATIC_INIT); @@ -576,24 +633,14 @@ class DirectMethodHandle extends MethodHandle { assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind); // getObject, putIntVolatile, etc. - StringBuilder nameBuilder = new StringBuilder(); - if (isGetter) { - nameBuilder.append("get"); - } else { - nameBuilder.append("put"); - } - nameBuilder.append(fw.primitiveSimpleName()); - nameBuilder.setCharAt(3, Character.toUpperCase(nameBuilder.charAt(3))); - if (isVolatile) { - nameBuilder.append("Volatile"); - } + Kind kind = getFieldKind(isGetter, isVolatile, fw); MethodType linkerType; if (isGetter) linkerType = MethodType.methodType(ft, Object.class, long.class); else linkerType = MethodType.methodType(void.class, Object.class, long.class, ft); - MemberName linker = new MemberName(Unsafe.class, nameBuilder.toString(), linkerType, REF_invokeVirtual); + MemberName linker = new MemberName(Unsafe.class, kind.methodName, linkerType, REF_invokeVirtual); try { linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, NoSuchMethodException.class); } catch (ReflectiveOperationException ex) { @@ -620,6 +667,7 @@ class DirectMethodHandle extends MethodHandle { final int F_HOLDER = (isStatic ? nameCursor++ : -1); // static base if any final int F_OFFSET = nameCursor++; // Either static offset or field offset. final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1); + final int U_HOLDER = nameCursor++; // UNSAFE holder final int INIT_BAR = (needsInit ? nameCursor++ : -1); final int PRE_CAST = (needsCast && !isGetter ? nameCursor++ : -1); final int LINKER_CALL = nameCursor++; @@ -632,7 +680,7 @@ class DirectMethodHandle extends MethodHandle { names[PRE_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[SET_VALUE]); Object[] outArgs = new Object[1 + linkerType.parameterCount()]; assert(outArgs.length == (isGetter ? 3 : 4)); - outArgs[0] = UNSAFE; + outArgs[0] = names[U_HOLDER] = new Name(NF_UNSAFE); if (isStatic) { outArgs[1] = names[F_HOLDER] = new Name(NF_staticBase, names[DMH_THIS]); outArgs[2] = names[F_OFFSET] = new Name(NF_staticOffset, names[DMH_THIS]); @@ -650,6 +698,7 @@ class DirectMethodHandle extends MethodHandle { for (Name n : names) assert(n != null); // add some detail to the lambdaForm debugname, // significant only for debugging + StringBuilder nameBuilder = new StringBuilder(kind.methodName); if (isStatic) { nameBuilder.append("Static"); } else { @@ -657,7 +706,12 @@ class DirectMethodHandle extends MethodHandle { } if (needsCast) nameBuilder.append("Cast"); if (needsInit) nameBuilder.append("Init"); - return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT); + if (needsCast || needsInit) { + // can't use the pre-generated form when casting and/or initializing + return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT); + } else { + return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT, kind); + } } /** @@ -674,7 +728,8 @@ class DirectMethodHandle extends MethodHandle { NF_staticOffset, NF_checkCast, NF_allocateInstance, - NF_constructorMethod; + NF_constructorMethod, + NF_UNSAFE; static { try { NamedFunction nfs[] = { @@ -697,7 +752,9 @@ class DirectMethodHandle extends MethodHandle { NF_allocateInstance = new NamedFunction(DirectMethodHandle.class .getDeclaredMethod("allocateInstance", Object.class)), NF_constructorMethod = new NamedFunction(DirectMethodHandle.class - .getDeclaredMethod("constructorMethod", Object.class)) + .getDeclaredMethod("constructorMethod", Object.class)), + NF_UNSAFE = new NamedFunction(new MemberName(MethodHandleStatics.class + .getDeclaredField("UNSAFE"))) }; // Each nf must be statically invocable or we get tied up in our bootstraps. assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs)); diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java b/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java index 714e6268d25..d6aa23e232b 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java @@ -28,9 +28,11 @@ package java.lang.invoke; import java.util.Map; import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Opcodes; - import java.util.ArrayList; import java.util.HashSet; +import sun.invoke.util.Wrapper; + +import static java.lang.invoke.MethodHandleNatives.Constants.*; /** * Helper class to assist the GenerateJLIClassesPlugin to get access to @@ -66,14 +68,38 @@ class GenerateJLIClassesHelper { static byte[] generateDirectMethodHandleHolderClassBytes(String className, MethodType[] methodTypes, int[] types) { - LambdaForm[] forms = new LambdaForm[methodTypes.length]; - String[] names = new String[methodTypes.length]; - for (int i = 0; i < forms.length; i++) { - forms[i] = DirectMethodHandle.makePreparedLambdaForm(methodTypes[i], - types[i]); - names[i] = forms[i].kind.defaultLambdaName; + ArrayList forms = new ArrayList<>(); + ArrayList names = new ArrayList<>(); + for (int i = 0; i < methodTypes.length; i++) { + LambdaForm form = DirectMethodHandle + .makePreparedLambdaForm(methodTypes[i], types[i]); + forms.add(form); + names.add(form.kind.defaultLambdaName); } - return generateCodeBytesForLFs(className, names, forms); + for (Wrapper wrapper : Wrapper.values()) { + if (wrapper == Wrapper.VOID) { + continue; + } + for (byte b = DirectMethodHandle.AF_GETFIELD; b < DirectMethodHandle.AF_LIMIT; b++) { + int ftype = DirectMethodHandle.ftypeKind(wrapper.primitiveType()); + LambdaForm form = DirectMethodHandle + .makePreparedFieldLambdaForm(b, /*isVolatile*/false, ftype); + if (form.kind != LambdaForm.Kind.GENERIC) { + forms.add(form); + names.add(form.kind.defaultLambdaName); + } + // volatile + form = DirectMethodHandle + .makePreparedFieldLambdaForm(b, /*isVolatile*/true, ftype); + if (form.kind != LambdaForm.Kind.GENERIC) { + forms.add(form); + names.add(form.kind.defaultLambdaName); + } + } + } + return generateCodeBytesForLFs(className, + names.toArray(new String[0]), + forms.toArray(new LambdaForm[0])); } static byte[] generateDelegatingMethodHandleHolderClassBytes(String className, @@ -166,4 +192,5 @@ class GenerateJLIClassesHelper { BoundMethodHandle.Factory.generateConcreteBMHClassBytes( shortTypes, types, className)); } + } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 6b9a2703be2..b72f94324ef 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -629,6 +629,24 @@ class InvokerBytecodeGenerator { name = name + "_" + form.returnType().basicTypeChar(); return resolveFrom(name, invokerType, LambdaForm.Holder.class); } + case GET_OBJECT: // fall-through + case GET_BOOLEAN: // fall-through + case GET_BYTE: // fall-through + case GET_CHAR: // fall-through + case GET_SHORT: // fall-through + case GET_INT: // fall-through + case GET_LONG: // fall-through + case GET_FLOAT: // fall-through + case GET_DOUBLE: // fall-through + case PUT_OBJECT: // fall-through + case PUT_BOOLEAN: // fall-through + case PUT_BYTE: // fall-through + case PUT_CHAR: // fall-through + case PUT_SHORT: // fall-through + case PUT_INT: // fall-through + case PUT_LONG: // fall-through + case PUT_FLOAT: // fall-through + case PUT_DOUBLE: // fall-through case DIRECT_INVOKE_INTERFACE: // fall-through case DIRECT_INVOKE_SPECIAL: // fall-through case DIRECT_INVOKE_STATIC: // fall-through diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java index a7c84c823ea..792984eb16d 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java @@ -280,7 +280,43 @@ class LambdaForm { DIRECT_INVOKE_STATIC("DMH.invokeStatic"), DIRECT_NEW_INVOKE_SPECIAL("DMH.newInvokeSpecial"), DIRECT_INVOKE_INTERFACE("DMH.invokeInterface"), - DIRECT_INVOKE_STATIC_INIT("DMH.invokeStaticInit"); + DIRECT_INVOKE_STATIC_INIT("DMH.invokeStaticInit"), + GET_OBJECT("getObject"), + PUT_OBJECT("putObject"), + GET_OBJECT_VOLATILE("getObjectVolatile"), + PUT_OBJECT_VOLATILE("putObjectVolatile"), + GET_INT("getInt"), + PUT_INT("putInt"), + GET_INT_VOLATILE("getIntVolatile"), + PUT_INT_VOLATILE("putIntVolatile"), + GET_BOOLEAN("getBoolean"), + PUT_BOOLEAN("putBoolean"), + GET_BOOLEAN_VOLATILE("getBooleanVolatile"), + PUT_BOOLEAN_VOLATILE("putBooleanVolatile"), + GET_BYTE("getByte"), + PUT_BYTE("putByte"), + GET_BYTE_VOLATILE("getByteVolatile"), + PUT_BYTE_VOLATILE("putByteVolatile"), + GET_CHAR("getChar"), + PUT_CHAR("putChar"), + GET_CHAR_VOLATILE("getCharVolatile"), + PUT_CHAR_VOLATILE("putCharVolatile"), + GET_SHORT("getShort"), + PUT_SHORT("putShort"), + GET_SHORT_VOLATILE("getShortVolatile"), + PUT_SHORT_VOLATILE("putShortVolatile"), + GET_LONG("getLong"), + PUT_LONG("putLong"), + GET_LONG_VOLATILE("getLongVolatile"), + PUT_LONG_VOLATILE("putLongVolatile"), + GET_FLOAT("getFloat"), + PUT_FLOAT("putFloat"), + GET_FLOAT_VOLATILE("getFloatVolatile"), + PUT_FLOAT_VOLATILE("putFloatVolatile"), + GET_DOUBLE("getDouble"), + PUT_DOUBLE("putDouble"), + GET_DOUBLE_VOLATILE("getDoubleVolatile"), + PUT_DOUBLE_VOLATILE("putDoubleVolatile"); final String defaultLambdaName; final String methodName; From 60754ca0fb92629089cb50b3ed7083b578ec3cf9 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Wed, 24 Aug 2016 16:11:21 +0200 Subject: [PATCH 19/51] 8164569: Generate non-customized invoker forms at link time Reviewed-by: vlivanov --- .../lang/invoke/GenerateJLIClassesHelper.java | 28 +++++ .../lang/invoke/InvokerBytecodeGenerator.java | 4 + .../classes/java/lang/invoke/Invokers.java | 30 +++-- .../classes/java/lang/invoke/LambdaForm.java | 8 ++ .../java/lang/invoke/MethodHandleImpl.java | 7 ++ .../internal/misc/JavaLangInvokeAccess.java | 15 ++- .../plugins/GenerateJLIClassesPlugin.java | 114 ++++++++++++------ .../lang/StackWalker/VerifyStackTrace.java | 7 +- 8 files changed, 164 insertions(+), 49 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java b/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java index d6aa23e232b..d8e6dcd5ed0 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java @@ -133,6 +133,34 @@ class GenerateJLIClassesHelper { forms.toArray(new LambdaForm[0])); } + static byte[] generateInvokersHolderClassBytes(String className, + MethodType[] methodTypes) { + + HashSet dedupSet = new HashSet<>(); + ArrayList forms = new ArrayList<>(); + ArrayList names = new ArrayList<>(); + int[] types = { + MethodTypeForm.LF_EX_LINKER, + MethodTypeForm.LF_EX_INVOKER, + MethodTypeForm.LF_GEN_LINKER, + MethodTypeForm.LF_GEN_INVOKER + }; + for (int i = 0; i < methodTypes.length; i++) { + // generate methods representing invokers of the specified type + if (dedupSet.add(methodTypes[i])) { + for (int type : types) { + LambdaForm invokerForm = Invokers.invokeHandleForm(methodTypes[i], + /*customized*/false, type); + forms.add(invokerForm); + names.add(invokerForm.kind.defaultLambdaName); + } + } + } + return generateCodeBytesForLFs(className, + names.toArray(new String[0]), + forms.toArray(new LambdaForm[0])); + } + /* * Generate customized code for a set of LambdaForms of specified types into * a class with a specified name. diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index b72f94324ef..b71bd527608 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -629,6 +629,10 @@ class InvokerBytecodeGenerator { name = name + "_" + form.returnType().basicTypeChar(); return resolveFrom(name, invokerType, LambdaForm.Holder.class); } + case EXACT_INVOKER: // fall-through + case EXACT_LINKER: // fall-through + case GENERIC_INVOKER: // fall-through + case GENERIC_LINKER: return resolveFrom(name, invokerType.basicType(), Invokers.Holder.class); case GET_OBJECT: // fall-through case GET_BOOLEAN: // fall-through case GET_BYTE: // fall-through diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java index 1aca86298fe..0a97622fe84 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java @@ -36,6 +36,7 @@ import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.LambdaForm.Kind.*; /** * Construction and caching of often-used invokers. @@ -254,7 +255,7 @@ class Invokers { * @param which bit-encoded 0x01 whether it is a CP adapter ("linker") or MHs.invoker value ("invoker"); * 0x02 whether it is for invokeExact or generic invoke */ - private static LambdaForm invokeHandleForm(MethodType mtype, boolean customized, int which) { + static LambdaForm invokeHandleForm(MethodType mtype, boolean customized, int which) { boolean isCached; if (!customized) { mtype = mtype.basicType(); // normalize Z to I, String to Object, etc. @@ -263,12 +264,12 @@ class Invokers { isCached = false; // maybe cache if mtype == mtype.basicType() } boolean isLinker, isGeneric; - String debugName; + Kind kind; switch (which) { - case MethodTypeForm.LF_EX_LINKER: isLinker = true; isGeneric = false; debugName = "invokeExact_MT"; break; - case MethodTypeForm.LF_EX_INVOKER: isLinker = false; isGeneric = false; debugName = "exactInvoker"; break; - case MethodTypeForm.LF_GEN_LINKER: isLinker = true; isGeneric = true; debugName = "invoke_MT"; break; - case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true; debugName = "invoker"; break; + case MethodTypeForm.LF_EX_LINKER: isLinker = true; isGeneric = false; kind = EXACT_LINKER; break; + case MethodTypeForm.LF_EX_INVOKER: isLinker = false; isGeneric = false; kind = EXACT_INVOKER; break; + case MethodTypeForm.LF_GEN_LINKER: isLinker = true; isGeneric = true; kind = GENERIC_LINKER; break; + case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true; kind = GENERIC_INVOKER; break; default: throw new InternalError(); } LambdaForm lform; @@ -323,7 +324,11 @@ class Invokers { names[CHECK_CUSTOM] = new Name(NF_checkCustomized, outArgs[0]); } names[LINKER_CALL] = new Name(outCallType, outArgs); - lform = new LambdaForm(debugName, INARG_LIMIT, names); + if (customized) { + lform = new LambdaForm(kind.defaultLambdaName, INARG_LIMIT, names); + } else { + lform = new LambdaForm(kind.defaultLambdaName, INARG_LIMIT, names, kind); + } if (isLinker) lform.compileToBytecode(); // JVM needs a real methodOop if (isCached) @@ -614,4 +619,15 @@ class Invokers { } } } + + static { + // The Holder class will contain pre-generated Invokers resolved + // speculatively using MemberName.getFactory().resolveOrNull. However, that + // doesn't initialize the class, which subtly breaks inlining etc. By forcing + // initialization of the Holder class we avoid these issues. + UNSAFE.ensureClassInitialized(Holder.class); + } + + /* Placeholder class for Invokers generated ahead of time */ + final class Holder {} } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java index 792984eb16d..f2e0372e855 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java @@ -275,6 +275,10 @@ class LambdaForm { BOUND_REINVOKER("BMH.reinvoke"), REINVOKER("MH.reinvoke"), DELEGATE("MH.delegate"), + EXACT_LINKER("MH.invokeExact_MT"), + EXACT_INVOKER("MH.exactInvoker"), + GENERIC_LINKER("MH.invoke_MT"), + GENERIC_INVOKER("MH.invoker"), DIRECT_INVOKE_VIRTUAL("DMH.invokeVirtual"), DIRECT_INVOKE_SPECIAL("DMH.invokeSpecial"), DIRECT_INVOKE_STATIC("DMH.invokeStatic"), @@ -365,6 +369,10 @@ class LambdaForm { int arity, Name[] names) { this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null, Kind.GENERIC); } + LambdaForm(String debugName, + int arity, Name[] names, Kind kind) { + this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null, kind); + } LambdaForm(String debugName, int arity, Name[] names, boolean forceInline) { this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null, Kind.GENERIC); diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index 4d0c2890fdf..4fe4bb524a7 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -1745,6 +1745,13 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; return GenerateJLIClassesHelper .generateBasicFormsClassBytes(className); } + + @Override + public byte[] generateInvokersHolderClassBytes(final String className, + MethodType[] methodTypes) { + return GenerateJLIClassesHelper + .generateInvokersHolderClassBytes(className, methodTypes); + } }); } diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java index 867853f22e8..c710c6543ef 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java @@ -46,7 +46,7 @@ public interface JavaLangInvokeAccess { boolean isNative(Object mname); /** - * Returns a {@code byte[]} containing the bytecode for a class implementing + * Returns a {@code byte[]} representation of a class implementing * DirectMethodHandle of each pairwise combination of {@code MethodType} and * an {@code int} representing method type. Used by * GenerateJLIClassesPlugin to generate such a class during the jlink phase. @@ -55,7 +55,7 @@ public interface JavaLangInvokeAccess { MethodType[] methodTypes, int[] types); /** - * Returns a {@code byte[]} containing the bytecode for a class implementing + * Returns a {@code byte[]} representation of a class implementing * DelegatingMethodHandles of each {@code MethodType} kind in the * {@code methodTypes} argument. Used by GenerateJLIClassesPlugin to * generate such a class during the jlink phase. @@ -64,7 +64,7 @@ public interface JavaLangInvokeAccess { MethodType[] methodTypes); /** - * Returns a {@code byte[]} containing the bytecode for a BoundMethodHandle + * Returns a {@code byte[]} representation of {@code BoundMethodHandle} * species class implementing the signature defined by {@code types}. Used * by GenerateBMHClassesPlugin to enable generation of such classes during * the jlink phase. Should do some added validation since this string may be @@ -74,8 +74,15 @@ public interface JavaLangInvokeAccess { final String types); /** - * Returns a {@code byte[]} containing the bytecode for a class implementing + * Returns a {@code byte[]} representation of a class implementing * the zero and identity forms of all {@code LambdaForm.BasicType}s. */ byte[] generateBasicFormsClassBytes(final String className); + + /** + * Returns a {@code byte[]} representation of a class implementing + * the invoker forms for the set of supplied {@code methodTypes}. + */ + byte[] generateInvokersHolderClassBytes(String className, + MethodType[] methodTypes); } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java index d59bc8a2341..514d1b7528e 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java @@ -48,14 +48,12 @@ public final class GenerateJLIClassesPlugin implements Plugin { private static final String NAME = "generate-jli-classes"; private static final String BMH_PARAM = "bmh"; - private static final String BMH_SPECIES_PARAM = "bmh-species"; - private static final String DMH_PARAM = "dmh"; - private static final String DESCRIPTION = PluginsResourceBundle.getDescription(NAME); - private static final String DIRECT_METHOD_HANDLE = "java/lang/invoke/DirectMethodHandle$Holder"; + private static final String DMH_PARAM = "dmh"; + private static final String DIRECT_HOLDER = "java/lang/invoke/DirectMethodHandle$Holder"; private static final String DMH_INVOKE_VIRTUAL = "invokeVirtual"; private static final String DMH_INVOKE_STATIC = "invokeStatic"; private static final String DMH_INVOKE_SPECIAL = "invokeSpecial"; @@ -63,17 +61,22 @@ public final class GenerateJLIClassesPlugin implements Plugin { private static final String DMH_INVOKE_INTERFACE = "invokeInterface"; private static final String DMH_INVOKE_STATIC_INIT = "invokeStaticInit"; - private static final String DELEGATING_METHOD_HANDLE = "java/lang/invoke/DelegatingMethodHandle$Holder"; + private static final String INVOKERS_PARAM = "invokers"; - private static final String BASIC_FORMS_HANDLE = "java/lang/invoke/LambdaForm$Holder"; + private static final String DELEGATING_HOLDER = "java/lang/invoke/DelegatingMethodHandle$Holder"; + private static final String BASIC_FORMS_HOLDER = "java/lang/invoke/LambdaForm$Holder"; + private static final String INVOKERS_HOLDER = "java/lang/invoke/Invokers$Holder"; private static final JavaLangInvokeAccess JLIA = SharedSecrets.getJavaLangInvokeAccess(); List speciesTypes; + List invokerTypes; + Map> dmhMethods; + public GenerateJLIClassesPlugin() { } @@ -116,6 +119,13 @@ public final class GenerateJLIClassesPlugin implements Plugin { "LILL", "I", "LLILL"); } + /** + * @return the default invoker forms to generate. + */ + public static List defaultInvokers() { + return List.of("_L", "_I", "I_I", "LI_I", "ILL_I", "LIL_I", "L_L", "LL_V", "LLLL_L"); + } + /** * @return the list of default DirectMethodHandle methods to generate. */ @@ -153,6 +163,7 @@ public final class GenerateJLIClassesPlugin implements Plugin { // Enable by default boolean bmhEnabled = true; boolean dmhEnabled = true; + boolean invokersEnabled = true; if (mainArgument != null) { List args = Arrays.asList(mainArgument.split(",")); if (!args.contains(BMH_PARAM)) { @@ -161,6 +172,9 @@ public final class GenerateJLIClassesPlugin implements Plugin { if (!args.contains(DMH_PARAM)) { dmhEnabled = false; } + if (!args.contains(INVOKERS_PARAM)) { + dmhEnabled = false; + } } if (!bmhEnabled) { @@ -183,6 +197,21 @@ public final class GenerateJLIClassesPlugin implements Plugin { .collect(Collectors.toList()); } + if (!invokersEnabled) { + invokerTypes = List.of(); + } else { + String args = config.get(INVOKERS_PARAM); + if (args != null && !args.isEmpty()) { + invokerTypes = Arrays.stream(args.split(",")) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .collect(Collectors.toList()); + validateMethodTypes(invokerTypes); + } else { + invokerTypes = defaultInvokers(); + } + + } // DirectMethodHandles if (!dmhEnabled) { dmhMethods = Map.of(); @@ -196,18 +225,7 @@ public final class GenerateJLIClassesPlugin implements Plugin { .filter(s -> !s.isEmpty()) .collect(Collectors.toList()); dmhMethods.put(dmhParam, dmhMethodTypes); - // Validation check - for (String type : dmhMethodTypes) { - String[] typeParts = type.split("_"); - // check return type (second part) - if (typeParts.length != 2 || typeParts[1].length() != 1 - || "LJIFDV".indexOf(typeParts[1].charAt(0)) == -1) { - throw new PluginException( - "Method type signature must be of form [LJIFD]*_[LJIFDV]"); - } - // expand and check arguments (first part) - expandSignature(typeParts[0]); - } + validateMethodTypes(dmhMethodTypes); } } if (dmhMethods.isEmpty()) { @@ -216,6 +234,20 @@ public final class GenerateJLIClassesPlugin implements Plugin { } } + void validateMethodTypes(List dmhMethodTypes) { + for (String type : dmhMethodTypes) { + String[] typeParts = type.split("_"); + // check return type (second part) + if (typeParts.length != 2 || typeParts[1].length() != 1 + || "LJIFDV".indexOf(typeParts[1].charAt(0)) == -1) { + throw new PluginException( + "Method type signature must be of form [LJIFD]*_[LJIFDV]"); + } + // expand and check arguments (first part) + expandSignature(typeParts[0]); + } + } + private static void requireBasicType(char c) { if ("LIJFD".indexOf(c) < 0) { throw new PluginException( @@ -228,9 +260,10 @@ public final class GenerateJLIClassesPlugin implements Plugin { // Copy all but DMH_ENTRY to out in.transformAndCopy(entry -> { // filter out placeholder entries - if (entry.path().equals(DIRECT_METHOD_HANDLE_ENTRY) || - entry.path().equals(DELEGATING_METHOD_HANDLE_ENTRY) || - entry.path().equals(BASIC_FORMS_HANDLE_ENTRY)) { + if (entry.path().equals(DIRECT_METHOD_HOLDER_ENTRY) || + entry.path().equals(DELEGATING_METHOD_HOLDER_ENTRY) || + entry.path().equals(INVOKERS_HOLDER_ENTRY) || + entry.path().equals(BASIC_FORMS_HOLDER_ENTRY)) { return null; } else { return entry; @@ -265,42 +298,53 @@ public final class GenerateJLIClassesPlugin implements Plugin { for (List entry : dmhMethods.values()) { count += entry.size(); } - MethodType[] methodTypes = new MethodType[count]; + MethodType[] directMethodTypes = new MethodType[count]; int[] dmhTypes = new int[count]; int index = 0; for (Map.Entry> entry : dmhMethods.entrySet()) { String dmhType = entry.getKey(); for (String type : entry.getValue()) { - methodTypes[index] = asMethodType(type); + directMethodTypes[index] = asMethodType(type); dmhTypes[index] = DMH_METHOD_TYPE_MAP.get(dmhType); index++; } } + MethodType[] invokerMethodTypes = new MethodType[this.invokerTypes.size()]; + for (int i = 0; i < invokerTypes.size(); i++) { + invokerMethodTypes[i] = asMethodType(invokerTypes.get(i)); + } try { byte[] bytes = JLIA.generateDirectMethodHandleHolderClassBytes( - DIRECT_METHOD_HANDLE, methodTypes, dmhTypes); + DIRECT_HOLDER, directMethodTypes, dmhTypes); ResourcePoolEntry ndata = ResourcePoolEntry - .create(DIRECT_METHOD_HANDLE_ENTRY, bytes); + .create(DIRECT_METHOD_HOLDER_ENTRY, bytes); out.add(ndata); bytes = JLIA.generateDelegatingMethodHandleHolderClassBytes( - DELEGATING_METHOD_HANDLE, methodTypes); - ndata = ResourcePoolEntry.create(DELEGATING_METHOD_HANDLE_ENTRY, bytes); + DELEGATING_HOLDER, directMethodTypes); + ndata = ResourcePoolEntry.create(DELEGATING_METHOD_HOLDER_ENTRY, bytes); out.add(ndata); - bytes = JLIA.generateBasicFormsClassBytes(BASIC_FORMS_HANDLE); - ndata = ResourcePoolEntry.create(BASIC_FORMS_HANDLE_ENTRY, bytes); + bytes = JLIA.generateInvokersHolderClassBytes(INVOKERS_HOLDER, + invokerMethodTypes); + ndata = ResourcePoolEntry.create(INVOKERS_HOLDER_ENTRY, bytes); + out.add(ndata); + + bytes = JLIA.generateBasicFormsClassBytes(BASIC_FORMS_HOLDER); + ndata = ResourcePoolEntry.create(BASIC_FORMS_HOLDER_ENTRY, bytes); out.add(ndata); } catch (Exception ex) { throw new PluginException(ex); } } - private static final String DIRECT_METHOD_HANDLE_ENTRY = - "/java.base/" + DIRECT_METHOD_HANDLE + ".class"; - private static final String DELEGATING_METHOD_HANDLE_ENTRY = - "/java.base/" + DELEGATING_METHOD_HANDLE + ".class"; - private static final String BASIC_FORMS_HANDLE_ENTRY = - "/java.base/" + BASIC_FORMS_HANDLE + ".class"; + private static final String DIRECT_METHOD_HOLDER_ENTRY = + "/java.base/" + DIRECT_HOLDER + ".class"; + private static final String DELEGATING_METHOD_HOLDER_ENTRY = + "/java.base/" + DELEGATING_HOLDER + ".class"; + private static final String BASIC_FORMS_HOLDER_ENTRY = + "/java.base/" + BASIC_FORMS_HOLDER + ".class"; + private static final String INVOKERS_HOLDER_ENTRY = + "/java.base/" + INVOKERS_HOLDER + ".class"; // Convert LL -> LL, L3 -> LLL private static String expandSignature(String signature) { diff --git a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java index 2c70a6d02dc..704a807bc57 100644 --- a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java +++ b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java @@ -205,12 +205,13 @@ public class VerifyStackTrace { .replaceAll("java.base@(\\d+\\.){0,3}(\\d+)/", "java.base/") .replaceAll("/[0-9]+\\.run", "/xxxxxxxx.run") .replaceAll("/[0-9]+\\.invoke", "/xxxxxxxx.invoke") - // DMHs may or may not be pre-generated, making frames differ + // LFs may or may not be pre-generated, making frames differ .replaceAll("DirectMethodHandle\\$Holder", "LambdaForm\\$DMH") - .replaceAll("DMH\\.invoke", "DMH/xxxxxxxx.invoke") + .replaceAll("Invokers\\$Holder", "LambdaForm\\$MH") + .replaceAll("MH\\.invoke", "MH/xxxxxxxx.invoke") // invoke frames may or may not have basic method type // information encoded for diagnostic purposes - .replaceAll("xx\\.invoke([A-Za-z]*)_[A-Z]+_[A-Z]", "xx.invoke$1") + .replaceAll("xx\\.invoke([A-Za-z]*)_[A-Z_]+", "xx.invoke$1") .replaceAll("\\$[0-9]+", "\\$??"); } else { return produced; From dde76394d5fd7fa4b40fef5516acca3d24df4ee5 Mon Sep 17 00:00:00 2001 From: Sean Coffey Date: Wed, 24 Aug 2016 17:57:20 +0100 Subject: [PATCH 20/51] 8150530: Improve javax.crypto.BadPaddingException messages Reviewed-by: xuelei --- .../com/sun/crypto/provider/CipherCore.java | 5 +++-- .../classes/sun/security/rsa/RSAPadding.java | 7 ++++-- .../classes/sun/security/ssl/CipherBox.java | 22 ++++++++++++++----- .../sun/security/pkcs11/P11RSACipher.java | 4 +++- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java b/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java index 592ec411407..106ee91392c 100644 --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java @@ -986,8 +986,9 @@ final class CipherCore { if (padding != null) { int padStart = padding.unpad(outWithPadding, 0, outLen); if (padStart < 0) { - throw new BadPaddingException("Given final block not " - + "properly padded"); + throw new BadPaddingException("Given final block not " + + "properly padded. Such issues can arise if a bad key " + + "is used during decryption."); } outLen = padStart; } diff --git a/jdk/src/java.base/share/classes/sun/security/rsa/RSAPadding.java b/jdk/src/java.base/share/classes/sun/security/rsa/RSAPadding.java index d236c346d87..d757a192b81 100644 --- a/jdk/src/java.base/share/classes/sun/security/rsa/RSAPadding.java +++ b/jdk/src/java.base/share/classes/sun/security/rsa/RSAPadding.java @@ -253,7 +253,8 @@ public final class RSAPadding { public byte[] pad(byte[] data) throws BadPaddingException { if (data.length > maxDataSize) { throw new BadPaddingException("Data must be shorter than " - + (maxDataSize + 1) + " bytes"); + + (maxDataSize + 1) + " bytes but received " + + data.length + " bytes."); } switch (type) { case PAD_NONE: @@ -281,7 +282,9 @@ public final class RSAPadding { */ public byte[] unpad(byte[] padded) throws BadPaddingException { if (padded.length != paddedSize) { - throw new BadPaddingException("Decryption error"); + throw new BadPaddingException("Decryption error." + + "The padded array length (" + padded.length + + ") is not the specified padded size (" + paddedSize + ")"); } switch (type) { case PAD_NONE: diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/CipherBox.java b/jdk/src/java.base/share/classes/sun/security/ssl/CipherBox.java index 57a3e1e8aa6..2056d2fe7a2 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/CipherBox.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/CipherBox.java @@ -493,7 +493,9 @@ final class CipherBox { if (protocolVersion.useTLS11PlusSpec()) { if (newLen < blockSize) { - throw new BadPaddingException("invalid explicit IV"); + throw new BadPaddingException("The length after " + + "padding removal (" + newLen + ") should be larger " + + "than <" + blockSize + "> since explicit IV used"); } } } @@ -504,7 +506,6 @@ final class CipherBox { } } - /* * Decrypts a block of data, returning the size of the * resulting block if padding was required. position and limit @@ -575,7 +576,9 @@ final class CipherBox { // check the explicit IV of TLS v1.1 or later if (protocolVersion.useTLS11PlusSpec()) { if (newLen < blockSize) { - throw new BadPaddingException("invalid explicit IV"); + throw new BadPaddingException("The length after " + + "padding removal (" + newLen + ") should be larger " + + "than <" + blockSize + "> since explicit IV used"); } // reset the position to the end of the decrypted data @@ -756,7 +759,9 @@ final class CipherBox { // so accept that as well // v3 does not require any particular value for the other bytes if (padLen > blockSize) { - throw new BadPaddingException("Invalid SSLv3 padding"); + throw new BadPaddingException("Padding length (" + + padLen + ") of SSLv3 message should not be bigger " + + "than the block size (" + blockSize + ")"); } } return newLen; @@ -802,7 +807,9 @@ final class CipherBox { // so accept that as well // v3 does not require any particular value for the other bytes if (padLen > blockSize) { - throw new BadPaddingException("Invalid SSLv3 padding"); + throw new BadPaddingException("Padding length (" + + padLen + ") of SSLv3 message should not be bigger " + + "than the block size (" + blockSize + ")"); } } @@ -925,7 +932,10 @@ final class CipherBox { case AEAD_CIPHER: if (bb.remaining() < (recordIvSize + tagSize)) { throw new BadPaddingException( - "invalid AEAD cipher fragment"); + "Insufficient buffer remaining for AEAD cipher " + + "fragment (" + bb.remaining() + "). Needs to be " + + "more than or equal to IV size (" + recordIvSize + + ") + tag size (" + tagSize + ")"); } // initialize the AEAD cipher for the unique IV diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11RSACipher.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11RSACipher.java index 58a4e2f545d..164ae0c6c02 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11RSACipher.java +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11RSACipher.java @@ -358,7 +358,9 @@ final class P11RSACipher extends CipherSpi { System.arraycopy(buffer, 0, tmpBuffer, 0, bufOfs); tmpBuffer = p11.C_Sign(session.id(), tmpBuffer); if (tmpBuffer.length > outLen) { - throw new BadPaddingException("Output buffer too small"); + throw new BadPaddingException( + "Output buffer (" + outLen + ") is too small to " + + "hold the produced data (" + tmpBuffer.length + ")"); } System.arraycopy(tmpBuffer, 0, out, outOfs, tmpBuffer.length); n = tmpBuffer.length; From 8fe1b11fa9aa3e5a2e68b4da6ef0806de62a542a Mon Sep 17 00:00:00 2001 From: Artem Smotrakov Date: Wed, 24 Aug 2016 10:58:29 -0700 Subject: [PATCH 21/51] 8164166: Make sure java/nio/channels tests shutdown asynchronous channel groups Reviewed-by: alanb --- .../AsynchronousChannelGroup/Basic.java | 174 ++++++++++-------- .../AsynchronousChannelGroup/GroupOfOne.java | 146 +++++++-------- .../AsynchronousChannelGroup/Identity.java | 150 +++++++-------- .../AsynchronousChannelGroup/Restart.java | 91 ++++----- 4 files changed, 298 insertions(+), 263 deletions(-) diff --git a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Basic.java b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Basic.java index 0a62be8fc57..036b28dbf7f 100644 --- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Basic.java +++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -119,19 +119,31 @@ public class Basic { ExecutorService pool = Executors.newCachedThreadPool(); AsynchronousChannelGroup group = AsynchronousChannelGroup .withCachedThreadPool(pool, rand.nextInt(10)); - testShutdownWithChannels(pool, group); + try { + testShutdownWithChannels(pool, group); + } finally { + group.shutdown(); + } } for (int i = 0; i < 100; i++) { int nThreads = 1 + rand.nextInt(8); AsynchronousChannelGroup group = AsynchronousChannelGroup .withFixedThreadPool(nThreads, threadFactory); - testShutdownWithChannels(null, group); + try { + testShutdownWithChannels(null, group); + } finally { + group.shutdown(); + } } for (int i = 0; i < 100; i++) { ExecutorService pool = Executors.newCachedThreadPool(); AsynchronousChannelGroup group = AsynchronousChannelGroup .withThreadPool(pool); - testShutdownWithChannels(pool, group); + try { + testShutdownWithChannels(pool, group); + } finally { + group.shutdown(); + } } } @@ -164,19 +176,31 @@ public class Basic { ExecutorService pool = pool = Executors.newCachedThreadPool(); AsynchronousChannelGroup group = AsynchronousChannelGroup .withCachedThreadPool(pool, rand.nextInt(5)); - testShutdownNow(pool, group); + try { + testShutdownNow(pool, group); + } finally { + group.shutdown(); + } } for (int i = 0; i < 10; i++) { int nThreads = 1 + rand.nextInt(8); AsynchronousChannelGroup group = AsynchronousChannelGroup .withFixedThreadPool(nThreads, threadFactory); - testShutdownNow(null, group); + try { + testShutdownNow(null, group); + } finally { + group.shutdown(); + } } for (int i = 0; i < 10; i++) { ExecutorService pool = Executors.newCachedThreadPool(); AsynchronousChannelGroup group = AsynchronousChannelGroup .withThreadPool(pool); - testShutdownNow(pool, group); + try { + testShutdownNow(pool, group); + } finally { + group.shutdown(); + } } } @@ -186,78 +210,78 @@ public class Basic { AsynchronousChannelGroup group = AsynchronousChannelGroup.withFixedThreadPool(1, threadFactory); - AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group); - AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open(group); + try (AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group); + AsynchronousServerSocketChannel listener = + AsynchronousServerSocketChannel.open(group)) { - // initiate accept - listener.bind(new InetSocketAddress(0)); - Future result = listener.accept(); + // initiate accept + listener.bind(new InetSocketAddress(0)); + Future result = listener.accept(); - // shutdown group - group.shutdown(); - if (!group.isShutdown()) - throw new RuntimeException("Group should be shutdown"); + // shutdown group + group.shutdown(); + if (!group.isShutdown()) + throw new RuntimeException("Group should be shutdown"); - // attempt to create another channel - try { - AsynchronousSocketChannel.open(group); - throw new RuntimeException("ShutdownChannelGroupException expected"); - } catch (ShutdownChannelGroupException x) { + // attempt to create another channel + try { + AsynchronousSocketChannel.open(group); + throw new RuntimeException("ShutdownChannelGroupException expected"); + } catch (ShutdownChannelGroupException x) { + } + try { + AsynchronousServerSocketChannel.open(group); + throw new RuntimeException("ShutdownChannelGroupException expected"); + } catch (ShutdownChannelGroupException x) { + } + + // attempt to create another channel by connecting. This should cause + // the accept operation to fail. + InetAddress lh = InetAddress.getLocalHost(); + int port = ((InetSocketAddress)listener.getLocalAddress()).getPort(); + InetSocketAddress isa = new InetSocketAddress(lh, port); + ch.connect(isa).get(); + try { + result.get(); + throw new RuntimeException("Connection was accepted"); + } catch (ExecutionException x) { + Throwable cause = x.getCause(); + if (!(cause instanceof IOException)) + throw new RuntimeException("Cause should be IOException"); + cause = cause.getCause(); + if (!(cause instanceof ShutdownChannelGroupException)) + throw new RuntimeException("IOException cause should be ShutdownChannelGroupException"); + } + + // initiate another accept even though channel group is shutdown. + Future res = listener.accept(); + try { + res.get(3, TimeUnit.SECONDS); + throw new RuntimeException("TimeoutException expected"); + } catch (TimeoutException x) { + } + // connect to the listener which should cause the accept to complete + AsynchronousSocketChannel.open().connect(isa); + try { + res.get(); + throw new RuntimeException("Connection was accepted"); + } catch (ExecutionException x) { + Throwable cause = x.getCause(); + if (!(cause instanceof IOException)) + throw new RuntimeException("Cause should be IOException"); + cause = cause.getCause(); + if (!(cause instanceof ShutdownChannelGroupException)) + throw new RuntimeException("IOException cause should be ShutdownChannelGroupException"); + } + + // group should *not* terminate as channels are open + boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS); + if (terminated) { + throw new RuntimeException("Group should not have terminated"); + } + } finally { + group.shutdown(); } - try { - AsynchronousServerSocketChannel.open(group); - throw new RuntimeException("ShutdownChannelGroupException expected"); - } catch (ShutdownChannelGroupException x) { - } - - // attempt to create another channel by connecting. This should cause - // the accept operation to fail. - InetAddress lh = InetAddress.getLocalHost(); - int port = ((InetSocketAddress)listener.getLocalAddress()).getPort(); - InetSocketAddress isa = new InetSocketAddress(lh, port); - ch.connect(isa).get(); - try { - result.get(); - throw new RuntimeException("Connection was accepted"); - } catch (ExecutionException x) { - Throwable cause = x.getCause(); - if (!(cause instanceof IOException)) - throw new RuntimeException("Cause should be IOException"); - cause = cause.getCause(); - if (!(cause instanceof ShutdownChannelGroupException)) - throw new RuntimeException("IOException cause should be ShutdownChannelGroupException"); - } - - // initiate another accept even though channel group is shutdown. - Future res = listener.accept(); - try { - res.get(3, TimeUnit.SECONDS); - throw new RuntimeException("TimeoutException expected"); - } catch (TimeoutException x) { - } - // connect to the listener which should cause the accept to complete - AsynchronousSocketChannel.open().connect(isa); - try { - res.get(); - throw new RuntimeException("Connection was accepted"); - } catch (ExecutionException x) { - Throwable cause = x.getCause(); - if (!(cause instanceof IOException)) - throw new RuntimeException("Cause should be IOException"); - cause = cause.getCause(); - if (!(cause instanceof ShutdownChannelGroupException)) - throw new RuntimeException("IOException cause should be ShutdownChannelGroupException"); - } - - // group should *not* terminate as channels are open - boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS); - if (terminated) - throw new RuntimeException("Group should not have terminated"); - - // close channel; group should terminate quickly - ch.close(); - listener.close(); - awaitTermination(group); } static void miscTests() throws Exception { diff --git a/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java b/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java index ce7d3f63552..9740f953215 100644 --- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java +++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,34 +41,36 @@ import java.io.IOException; public class GroupOfOne { public static void main(String[] args) throws Exception { + final List accepted = new ArrayList<>(); + // create listener to accept connections - final AsynchronousServerSocketChannel listener = - AsynchronousServerSocketChannel.open() - .bind(new InetSocketAddress(0)); - final List accepted = new ArrayList(); - listener.accept((Void)null, new CompletionHandler() { - public void completed(AsynchronousSocketChannel ch, Void att) { - synchronized (accepted) { - accepted.add(ch); + try (final AsynchronousServerSocketChannel listener = + AsynchronousServerSocketChannel.open()) { + + listener.bind(new InetSocketAddress(0)); + listener.accept((Void)null, new CompletionHandler() { + public void completed(AsynchronousSocketChannel ch, Void att) { + synchronized (accepted) { + accepted.add(ch); + } + listener.accept((Void)null, this); } - listener.accept((Void)null, this); - } - public void failed(Throwable exc, Void att) { - } - }); + public void failed(Throwable exc, Void att) { + } + }); - int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort(); - SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port); + int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort(); + SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port); - test(sa, true, false); - test(sa, false, true); - test(sa, true, true); - - // clean-up - listener.close(); - synchronized (accepted) { - for (AsynchronousSocketChannel ch: accepted) { - ch.close(); + test(sa, true, false); + test(sa, false, true); + test(sa, true, true); + } finally { + // clean-up + synchronized (accepted) { + for (AsynchronousSocketChannel ch: accepted) { + ch.close(); + } } } } @@ -86,60 +88,60 @@ public class GroupOfOne { return new Thread(r); }}); final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group); + try { + // the latch counts down when: + // 1. The read operation fails (expected) + // 2. the close/shutdown completes + final CountDownLatch latch = new CountDownLatch(2); - // the latch counts down when: - // 1. The read operation fails (expected) - // 2. the close/shutdown completes - final CountDownLatch latch = new CountDownLatch(2); + ch.connect(sa, (Void)null, new CompletionHandler() { + public void completed(Void result, Void att) { + System.out.println("Connected"); - ch.connect(sa, (Void)null, new CompletionHandler() { - public void completed(Void result, Void att) { - System.out.println("Connected"); + // initiate I/O operation that does not complete (successfully) + ByteBuffer buf = ByteBuffer.allocate(100); + ch.read(buf, (Void)null, new CompletionHandler() { + public void completed(Integer bytesRead, Void att) { + throw new RuntimeException(); + } + public void failed(Throwable exc, Void att) { + if (!(exc instanceof AsynchronousCloseException)) + throw new RuntimeException(exc); + System.out.println("Read failed (expected)"); + latch.countDown(); + } + }); - // initiate I/O operation that does not complete (successfully) - ByteBuffer buf = ByteBuffer.allocate(100); - ch.read(buf, (Void)null, new CompletionHandler() { - public void completed(Integer bytesRead, Void att) { + // close channel or shutdown group + try { + if (closeChannel) { + System.out.print("Close channel ..."); + ch.close(); + System.out.println(" done."); + } + if (shutdownGroup) { + System.out.print("Shutdown group ..."); + group.shutdownNow(); + System.out.println(" done."); + } + latch.countDown(); + } catch (IOException e) { throw new RuntimeException(); } - public void failed(Throwable exc, Void att) { - if (!(exc instanceof AsynchronousCloseException)) - throw new RuntimeException(exc); - System.out.println("Read failed (expected)"); - latch.countDown(); - } - }); - - // close channel or shutdown group - try { - if (closeChannel) { - System.out.print("Close channel ..."); - ch.close(); - System.out.println(" done."); - } - if (shutdownGroup) { - System.out.print("Shutdown group ..."); - group.shutdownNow(); - System.out.println(" done."); - } - latch.countDown(); - } catch (IOException e) { - throw new RuntimeException(); } - } - public void failed(Throwable exc, Void att) { - throw new RuntimeException(exc); - } - }); - - latch.await(); - - // clean-up - group.shutdown(); - boolean terminated = group.awaitTermination(20, TimeUnit.SECONDS); - if (!terminated) - throw new RuntimeException("Group did not terminate"); + public void failed(Throwable exc, Void att) { + throw new RuntimeException(exc); + } + }); + latch.await(); + } finally { + // clean-up + group.shutdown(); + boolean terminated = group.awaitTermination(20, TimeUnit.SECONDS); + if (!terminated) + throw new RuntimeException("Group did not terminate"); + } System.out.println("TEST OKAY"); } } diff --git a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java index 654d5f92183..ef8c3a0ebf4 100644 --- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java +++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,89 +76,91 @@ public class Identity { } public static void main(String[] args) throws Exception { - // create listener to accept connections - final AsynchronousServerSocketChannel listener = - AsynchronousServerSocketChannel.open() - .bind(new InetSocketAddress(0)); - listener.accept((Void)null, new CompletionHandler() { - public void completed(final AsynchronousSocketChannel ch, Void att) { - listener.accept((Void)null, this); - final ByteBuffer buf = ByteBuffer.allocate(100); - ch.read(buf, ch, new CompletionHandler() { - public void completed(Integer bytesRead, AsynchronousSocketChannel ch) { - if (bytesRead < 0) { - try { ch.close(); } catch (IOException ignore) { } - } else { - buf.clear(); - ch.read(buf, ch, this); - } - } - public void failed(Throwable exc, AsynchronousSocketChannel ch) { - try { ch.close(); } catch (IOException ignore) { } - } - }); - } - public void failed(Throwable exc, Void att) { - } - }); - int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort(); - SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port); - // create 3-10 channels, each in its own group final int groupCount = 3 + rand.nextInt(8); - AsynchronousChannelGroup[] groups = new AsynchronousChannelGroup[groupCount]; + final AsynchronousChannelGroup[] groups = new AsynchronousChannelGroup[groupCount]; final AsynchronousSocketChannel[] channels = new AsynchronousSocketChannel[groupCount]; - for (int i=0; i() { - public void completed(Integer bytesWritten, Integer groupId) { - if (bytesWritten != 1) - fail("Expected 1 byte to be written"); - if (!myGroup.get().equals(groupId)) - fail("Handler invoked by thread with the wrong identity"); - if (writeCount.decrementAndGet() > 0) { - int id = rand.nextInt(groupCount); - channels[id].write(getBuffer(), id, this); - } else { - done.countDown(); + listener.bind(new InetSocketAddress(0)); + listener.accept((Void)null, new CompletionHandler() { + public void completed(final AsynchronousSocketChannel ch, Void att) { + listener.accept((Void)null, this); + final ByteBuffer buf = ByteBuffer.allocate(100); + ch.read(buf, ch, new CompletionHandler() { + public void completed(Integer bytesRead, AsynchronousSocketChannel ch) { + if (bytesRead < 0) { + try { ch.close(); } catch (IOException ignore) { } + } else { + buf.clear(); + ch.read(buf, ch, this); + } + } + public void failed(Throwable exc, AsynchronousSocketChannel ch) { + try { ch.close(); } catch (IOException ignore) { } + } + }); } + public void failed(Throwable exc, Void att) { + } + }); + int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort(); + SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port); + + for (int i=0; i() { + public void completed(Integer bytesWritten, Integer groupId) { + if (bytesWritten != 1) + fail("Expected 1 byte to be written"); + if (!myGroup.get().equals(groupId)) + fail("Handler invoked by thread with the wrong identity"); + if (writeCount.decrementAndGet() > 0) { + int id = rand.nextInt(groupCount); + channels[id].write(getBuffer(), id, this); + } else { + done.countDown(); + } + } + public void failed(Throwable exc, Integer groupId) { + fail(exc.getMessage()); + } + }); - // clean-up - for (AsynchronousSocketChannel ch: channels) - ch.close(); - for (AsynchronousChannelGroup group: groups) - group.shutdownNow(); - listener.close(); + // wait until done + done.await(); + } finally { + // clean-up + for (AsynchronousSocketChannel ch: channels) + ch.close(); + for (AsynchronousChannelGroup group: groups) + group.shutdownNow(); - if (failed.get()) - throw new RuntimeException("Test failed - see log for details"); + if (failed.get()) + throw new RuntimeException("Test failed - see log for details"); + } } static ByteBuffer getBuffer() { diff --git a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Restart.java b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Restart.java index 4d364017f0e..2c40bb71da1 100644 --- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Restart.java +++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Restart.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,21 +66,30 @@ public class Restart { // group with fixed thread pool int nThreads = 1 + rand.nextInt(4); AsynchronousChannelGroup group = - AsynchronousChannelGroup.withFixedThreadPool(nThreads, factory); - testRestart(group, 100); - group.shutdown(); + AsynchronousChannelGroup.withFixedThreadPool(nThreads, factory); + try { + testRestart(group, 100); + } finally { + group.shutdown(); + } // group with cached thread pool ExecutorService pool = Executors.newCachedThreadPool(factory); group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5)); - testRestart(group, 100); - group.shutdown(); + try { + testRestart(group, 100); + } finally { + group.shutdown(); + } // group with custom thread pool - group = AsynchronousChannelGroup - .withThreadPool(Executors.newFixedThreadPool(1+rand.nextInt(5), factory)); - testRestart(group, 100); - group.shutdown(); + group = AsynchronousChannelGroup.withThreadPool( + Executors.newFixedThreadPool(1+rand.nextInt(5), factory)); + try { + testRestart(group, 100); + } finally { + group.shutdown(); + } // give time for threads to terminate Thread.sleep(3000); @@ -92,45 +101,43 @@ public class Restart { static void testRestart(AsynchronousChannelGroup group, int count) throws Exception { - AsynchronousServerSocketChannel listener = - AsynchronousServerSocketChannel.open(group) - .bind(new InetSocketAddress(0)); + try (AsynchronousServerSocketChannel listener = + AsynchronousServerSocketChannel.open(group)) { - for (int i=0; i() { - public void completed(AsynchronousSocketChannel ch, Void att) { - try { - ch.close(); - } catch (IOException ignore) { } + listener.accept((Void)null, new CompletionHandler() { + public void completed(AsynchronousSocketChannel ch, Void att) { + try { + ch.close(); + } catch (IOException ignore) { } - latch.countDown(); + latch.countDown(); - // throw error or runtime exception - if (rand.nextBoolean()) { - throw new Error(); - } else { - throw new RuntimeException(); + // throw error or runtime exception + if (rand.nextBoolean()) { + throw new Error(); + } else { + throw new RuntimeException(); + } } - } - public void failed(Throwable exc, Void att) { - } - }); + public void failed(Throwable exc, Void att) { + } + }); - // establish loopback connection which should cause completion - // handler to be invoked. - int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort(); - AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); - InetAddress lh = InetAddress.getLocalHost(); - ch.connect(new InetSocketAddress(lh, port)).get(); - ch.close(); + // establish loopback connection which should cause completion + // handler to be invoked. + int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort(); + try (AsynchronousSocketChannel ch = AsynchronousSocketChannel.open()) { + InetAddress lh = InetAddress.getLocalHost(); + ch.connect(new InetSocketAddress(lh, port)).get(); + } - // wait for handler to be invoked - latch.await(); + // wait for handler to be invoked + latch.await(); + } } - - // clean-up - listener.close(); } } From 34565b8ada4a83e9e6cd0f0e0d1c473eb12c5046 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 24 Aug 2016 11:23:58 -0700 Subject: [PATCH 22/51] 8163136: Add print statements to java/nio/file/WatchService/LotsOfCancels.java Add some print statements. Reviewed-by: alanb --- .../nio/file/WatchService/LotsOfCancels.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/jdk/test/java/nio/file/WatchService/LotsOfCancels.java b/jdk/test/java/nio/file/WatchService/LotsOfCancels.java index 66597f35535..c5008e3ba5c 100644 --- a/jdk/test/java/nio/file/WatchService/LotsOfCancels.java +++ b/jdk/test/java/nio/file/WatchService/LotsOfCancels.java @@ -53,10 +53,11 @@ public class LotsOfCancels { Path testDir = Paths.get(System.getProperty("test.dir", ".")); Path top = Files.createTempDirectory(testDir, "LotsOfCancels"); for (int i=1; i<=16; i++) { + int id = i; Path dir = Files.createDirectory(top.resolve("dir-" + i)); WatchService watcher = FileSystems.getDefault().newWatchService(); - pool.submit(() -> handle(dir, watcher)); - pool.submit(() -> poll(watcher)); + pool.submit(() -> handle(id, dir, watcher)); + pool.submit(() -> poll(id, watcher)); } } finally { pool.shutdown(); @@ -74,7 +75,8 @@ public class LotsOfCancels { * Stress the given WatchService, specifically the cancel method, in * the given directory. Closes the WatchService when done. */ - static void handle(Path dir, WatchService watcher) { + static void handle(int id, Path dir, WatchService watcher) { + System.out.printf("begin handle %d%n", id); try { try { Path file = dir.resolve("anyfile"); @@ -85,12 +87,15 @@ public class LotsOfCancels { key.cancel(); } } finally { + System.out.printf("WatchService %d closing ...%n", id); watcher.close(); + System.out.printf("WatchService %d closed %n", id); } } catch (Exception e) { e.printStackTrace(); failed = true; } + System.out.printf("end handle %d%n", id); } /** @@ -98,7 +103,8 @@ public class LotsOfCancels { * queue drained, it also hogs a CPU core which seems necessary to * tickle the original bug. */ - static void poll(WatchService watcher) { + static void poll(int id, WatchService watcher) { + System.out.printf("begin poll %d%n", id); try { for (;;) { WatchKey key = watcher.take(); @@ -108,10 +114,12 @@ public class LotsOfCancels { } } } catch (ClosedWatchServiceException expected) { - // nothing to do + // nothing to do but print + System.out.printf("poll %d expected exception %s%n", id, expected); } catch (Exception e) { e.printStackTrace(); failed = true; } + System.out.printf("end poll %d%n", id); } } From 4c999ed180fa9937db895c2aa432db496f2ee63e Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Wed, 24 Aug 2016 12:50:37 -0700 Subject: [PATCH 23/51] 8163353: NPE in ConcurrentHashMap.removeAll() Reviewed-by: martin, psandoz, redestad, alanb --- .../java/util/concurrent/ConcurrentHashMap.java | 5 ++++- .../concurrent/tck/ConcurrentHashMapTest.java | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java index aadf3ca32a9..1d80077b58c 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java @@ -4566,7 +4566,10 @@ public class ConcurrentHashMap extends AbstractMap boolean modified = false; // Use (c instanceof Set) as a hint that lookup in c is as // efficient as this view - if (c instanceof Set && c.size() > map.table.length) { + Node[] t; + if ((t = map.table) == null) { + return false; + } else if (c instanceof Set && c.size() > t.length) { for (Iterator it = iterator(); it.hasNext(); ) { if (c.contains(it.next())) { it.remove(); diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java index c521b7edd58..26095ad1bb0 100644 --- a/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java +++ b/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java @@ -359,6 +359,21 @@ public class ConcurrentHashMapTest extends JSR166TestCase { assertTrue(s.contains(five)); } + /** + * Test keySet().removeAll on empty map + */ + public void testKeySet_empty_removeAll() { + ConcurrentHashMap map = new ConcurrentHashMap<>(); + Set set = map.keySet(); + set.removeAll(Collections.emptyList()); + assertTrue(map.isEmpty()); + assertTrue(set.isEmpty()); + // following is test for JDK-8163353 + set.removeAll(Collections.emptySet()); + assertTrue(map.isEmpty()); + assertTrue(set.isEmpty()); + } + /** * keySet.toArray returns contains all keys */ From 7b8ef7554e6dabdba0fae75cdeabf7d1c670d866 Mon Sep 17 00:00:00 2001 From: Srinivas Dama Date: Thu, 25 Aug 2016 09:43:46 +0530 Subject: [PATCH 24/51] 8163793: jlink has typo in copy-files plugin help text example Reviewed-by: sundar, redestad --- .../share/classes/jdk/tools/jlink/resources/plugins.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties index 50b958fa85d..6fa0248531f 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties @@ -56,7 +56,7 @@ copy-files.argument== to copy to the image>. copy-files.description=\ If files to copy are not absolute path, JDK home dir is used.\n\ -e.g.: jrt-fs.jar,LICENSE,/home/me/myfile.txt=somewehere/conf.txt +e.g.: jrt-fs.jar,LICENSE,/home/me/myfile.txt=somewhere/conf.txt exclude-files.argument= of files to exclude From 97fca016abdf03b662f787f422b9024edc11829e Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Thu, 25 Aug 2016 10:01:20 +0100 Subject: [PATCH 25/51] 8066943: (fs) Path.relativize() gives incorrect result for ".." Reviewed-by: prappo, bpb --- .../unix/classes/sun/nio/fs/UnixPath.java | 135 ++- .../classes/sun/nio/fs/WindowsPath.java | 83 +- jdk/test/java/nio/file/Path/PathOps.java | 1039 ++++++++++++++++- 3 files changed, 1167 insertions(+), 90 deletions(-) diff --git a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java index 8382c8cdfe8..1bcee895514 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java +++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java @@ -252,6 +252,21 @@ class UnixPath implements Path { return new UnixPath(getFileSystem(), new byte[0]); } + + // return true if this path has "." or ".." + private boolean hasDotOrDotDot() { + int n = getNameCount(); + for (int i=0; i cn) ? cn : bn; + int n = Math.min(baseCount, childCount); int i = 0; while (i < n) { - if (!this.getName(i).equals(other.getName(i))) + if (!base.getName(i).equals(child.getName(i))) break; i++; } - int dotdots = bn - i; - if (i < cn) { - // remaining name components in other - UnixPath remainder = other.subpath(i, cn); - if (dotdots == 0) - return remainder; - - // other is the empty path - boolean isOtherEmpty = other.isEmpty(); - - // result is a "../" for each remaining name in base - // followed by the remaining names in other. If the remainder is - // the empty path then we don't add the final trailing slash. - int len = dotdots*3 + remainder.path.length; - if (isOtherEmpty) { - assert remainder.isEmpty(); - len--; - } - byte[] result = new byte[len]; - int pos = 0; - while (dotdots > 0) { - result[pos++] = (byte)'.'; - result[pos++] = (byte)'.'; - if (isOtherEmpty) { - if (dotdots > 1) result[pos++] = (byte)'/'; - } else { - result[pos++] = (byte)'/'; - } - dotdots--; - } - System.arraycopy(remainder.path, 0, result, pos, remainder.path.length); - return new UnixPath(getFileSystem(), result); + // remaining elements in child + UnixPath childRemaining; + boolean isChildEmpty; + if (i == childCount) { + childRemaining = emptyPath(); + isChildEmpty = true; } else { - // no remaining names in other so result is simply a sequence of ".." - byte[] result = new byte[dotdots*3 - 1]; - int pos = 0; - while (dotdots > 0) { - result[pos++] = (byte)'.'; - result[pos++] = (byte)'.'; - // no tailing slash at the end - if (dotdots > 1) - result[pos++] = (byte)'/'; - dotdots--; - } - return new UnixPath(getFileSystem(), result); + childRemaining = child.subpath(i, childCount); + isChildEmpty = childRemaining.isEmpty(); } + + // matched all of base + if (i == baseCount) { + return childRemaining; + } + + // the remainder of base cannot contain ".." + UnixPath baseRemaining = base.subpath(i, baseCount); + if (baseRemaining.hasDotOrDotDot()) { + throw new IllegalArgumentException("Unable to compute relative " + + " path from " + this + " to " + obj); + } + if (baseRemaining.isEmpty()) + return childRemaining; + + // number of ".." needed + int dotdots = baseRemaining.getNameCount(); + if (dotdots == 0) { + return childRemaining; + } + + // result is a "../" for each remaining name in base followed by the + // remaining names in child. If the remainder is the empty path + // then we don't add the final trailing slash. + int len = dotdots*3 + childRemaining.path.length; + if (isChildEmpty) { + assert childRemaining.isEmpty(); + len--; + } + byte[] result = new byte[len]; + int pos = 0; + while (dotdots > 0) { + result[pos++] = (byte)'.'; + result[pos++] = (byte)'.'; + if (isChildEmpty) { + if (dotdots > 1) result[pos++] = (byte)'/'; + } else { + result[pos++] = (byte)'/'; + } + dotdots--; + } + System.arraycopy(childRemaining.path,0, result, pos, + childRemaining.path.length); + return new UnixPath(getFileSystem(), result); } @Override - public Path normalize() { + public UnixPath normalize() { final int count = getNameCount(); if (count == 0 || isEmpty()) return this; 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 b27f663de35..f4d70f94ad5 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 @@ -375,57 +375,108 @@ class WindowsPath implements Path { return (WindowsPath)path; } + // return true if this path has "." or ".." + private boolean hasDotOrDotDot() { + int n = getNameCount(); + for (int i=0; i cn) ? cn : bn; + int n = Math.min(baseCount, childCount); int i = 0; while (i < n) { - if (!this.getName(i).equals(other.getName(i))) + if (!base.getName(i).equals(child.getName(i))) break; i++; } - // append ..\ for remaining names in the base + // remaining elements in child + WindowsPath childRemaining; + boolean isChildEmpty; + if (i == childCount) { + childRemaining = emptyPath(); + isChildEmpty = true; + } else { + childRemaining = child.subpath(i, childCount); + isChildEmpty = childRemaining.isEmpty(); + } + + // matched all of base + if (i == baseCount) { + return childRemaining; + } + + // the remainder of base cannot contain ".." + WindowsPath baseRemaining = base.subpath(i, baseCount); + if (baseRemaining.hasDotOrDotDot()) { + throw new IllegalArgumentException("Unable to compute relative " + + " path from " + this + " to " + obj); + } + if (baseRemaining.isEmpty()) + return childRemaining; + + // number of ".." needed + int dotdots = baseRemaining.getNameCount(); + if (dotdots == 0) { + return childRemaining; + } + StringBuilder result = new StringBuilder(); - for (int j=i; j Date: Thu, 25 Aug 2016 13:29:47 +0200 Subject: [PATCH 26/51] 8164739: Remove computation of predefined interpreter forms Reviewed-by: vlivanov --- .../classes/java/lang/invoke/LambdaForm.java | 160 ------------------ 1 file changed, 160 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java index f2e0372e855..6fdf21e2c91 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java @@ -861,54 +861,6 @@ class LambdaForm { } } - private static void computeInitialPreparedForms() { - // Find all predefined invokers and associate them with canonical empty lambda forms. - for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) { - if (!m.isStatic() || !m.isPackage()) continue; - MethodType mt = m.getMethodType(); - if (mt.parameterCount() > 0 && - mt.parameterType(0) == MethodHandle.class && - m.getName().startsWith("interpret_")) { - String sig = null; - assert((sig = basicTypeSignature(mt)) != null && - m.getName().equals("interpret" + sig.substring(sig.indexOf('_')))); - LambdaForm form = new LambdaForm(mt); - form.vmentry = m; - form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, form); - } - } - } - - // Set this false to disable use of the interpret_L methods defined in this file. - private static final boolean USE_PREDEFINED_INTERPRET_METHODS = true; - - // The following are predefined exact invokers. The system must build - // a separate invoker for each distinct signature. - static Object interpret_L(MethodHandle mh) throws Throwable { - Object[] av = {mh}; - String sig = null; - assert(argumentTypesMatch(sig = "L_L", av)); - Object res = mh.form.interpretWithArguments(av); - assert(returnTypesMatch(sig, av, res)); - return res; - } - static Object interpret_L(MethodHandle mh, Object x1) throws Throwable { - Object[] av = {mh, x1}; - String sig = null; - assert(argumentTypesMatch(sig = "LL_L", av)); - Object res = mh.form.interpretWithArguments(av); - assert(returnTypesMatch(sig, av, res)); - return res; - } - static Object interpret_L(MethodHandle mh, Object x1, Object x2) throws Throwable { - Object[] av = {mh, x1, x2}; - String sig = null; - assert(argumentTypesMatch(sig = "LLL_L", av)); - Object res = mh.form.interpretWithArguments(av); - assert(returnTypesMatch(sig, av, res)); - return res; - } - // The next few routines are called only from assert expressions // They verify that the built-in invokers process the correct raw data types. private static boolean argumentTypesMatch(String sig, Object[] av) { @@ -1195,113 +1147,6 @@ class LambdaForm { return super.hashCode(); } - // Put the predefined NamedFunction invokers into the table. - static void initializeInvokers() { - for (MemberName m : MemberName.getFactory().getMethods(NamedFunction.class, false, null, null, null)) { - if (!m.isStatic() || !m.isPackage()) continue; - MethodType type = m.getMethodType(); - if (type.equals(INVOKER_METHOD_TYPE) && - m.getName().startsWith("invoke_")) { - String sig = m.getName().substring("invoke_".length()); - int arity = LambdaForm.signatureArity(sig); - MethodType srcType = MethodType.genericMethodType(arity); - if (LambdaForm.signatureReturn(sig) == V_TYPE) - srcType = srcType.changeReturnType(void.class); - MethodTypeForm typeForm = srcType.form(); - typeForm.setCachedMethodHandle(MethodTypeForm.MH_NF_INV, DirectMethodHandle.make(m)); - } - } - } - - // The following are predefined NamedFunction invokers. The system must build - // a separate invoker for each distinct signature. - /** void return type invokers. */ - @Hidden - static Object invoke__V(MethodHandle mh, Object[] a) throws Throwable { - assert(arityCheck(0, void.class, mh, a)); - mh.invokeBasic(); - return null; - } - @Hidden - static Object invoke_L_V(MethodHandle mh, Object[] a) throws Throwable { - assert(arityCheck(1, void.class, mh, a)); - mh.invokeBasic(a[0]); - return null; - } - @Hidden - static Object invoke_LL_V(MethodHandle mh, Object[] a) throws Throwable { - assert(arityCheck(2, void.class, mh, a)); - mh.invokeBasic(a[0], a[1]); - return null; - } - @Hidden - static Object invoke_LLL_V(MethodHandle mh, Object[] a) throws Throwable { - assert(arityCheck(3, void.class, mh, a)); - mh.invokeBasic(a[0], a[1], a[2]); - return null; - } - @Hidden - static Object invoke_LLLL_V(MethodHandle mh, Object[] a) throws Throwable { - assert(arityCheck(4, void.class, mh, a)); - mh.invokeBasic(a[0], a[1], a[2], a[3]); - return null; - } - @Hidden - static Object invoke_LLLLL_V(MethodHandle mh, Object[] a) throws Throwable { - assert(arityCheck(5, void.class, mh, a)); - mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]); - return null; - } - /** Object return type invokers. */ - @Hidden - static Object invoke__L(MethodHandle mh, Object[] a) throws Throwable { - assert(arityCheck(0, mh, a)); - return mh.invokeBasic(); - } - @Hidden - static Object invoke_L_L(MethodHandle mh, Object[] a) throws Throwable { - assert(arityCheck(1, mh, a)); - return mh.invokeBasic(a[0]); - } - @Hidden - static Object invoke_LL_L(MethodHandle mh, Object[] a) throws Throwable { - assert(arityCheck(2, mh, a)); - return mh.invokeBasic(a[0], a[1]); - } - @Hidden - static Object invoke_LLL_L(MethodHandle mh, Object[] a) throws Throwable { - assert(arityCheck(3, mh, a)); - return mh.invokeBasic(a[0], a[1], a[2]); - } - @Hidden - static Object invoke_LLLL_L(MethodHandle mh, Object[] a) throws Throwable { - assert(arityCheck(4, mh, a)); - return mh.invokeBasic(a[0], a[1], a[2], a[3]); - } - @Hidden - static Object invoke_LLLLL_L(MethodHandle mh, Object[] a) throws Throwable { - assert(arityCheck(5, mh, a)); - return mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]); - } - private static boolean arityCheck(int arity, MethodHandle mh, Object[] a) { - return arityCheck(arity, Object.class, mh, a); - } - private static boolean arityCheck(int arity, Class rtype, MethodHandle mh, Object[] a) { - assert(a.length == arity) - : Arrays.asList(a.length, arity); - assert(mh.type().basicType() == MethodType.genericMethodType(arity).changeReturnType(rtype)) - : Arrays.asList(mh, rtype, arity); - MemberName member = mh.internalMemberName(); - if (isInvokeBasic(member)) { - assert(arity > 0); - assert(a[0] instanceof MethodHandle); - MethodHandle mh2 = (MethodHandle) a[0]; - assert(mh2.type().basicType() == MethodType.genericMethodType(arity-1).changeReturnType(rtype)) - : Arrays.asList(member, mh2, rtype, arity); - } - return true; - } - static final MethodType INVOKER_METHOD_TYPE = MethodType.methodType(Object.class, MethodHandle.class, Object[].class); @@ -1964,12 +1809,7 @@ class LambdaForm { DEBUG_NAME_COUNTERS = null; } - // Put this last, so that previous static inits can run before. static { - if (USE_PREDEFINED_INTERPRET_METHODS) - computeInitialPreparedForms(); - NamedFunction.initializeInvokers(); - // The Holder class will contain pre-generated forms resolved // using MemberName.getFactory(). However, that doesn't initialize the // class, which subtly breaks inlining etc. By forcing From 87f1cd1d737d4b027d4a9ac777c901aab953cd73 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Thu, 25 Aug 2016 22:23:59 +0530 Subject: [PATCH 27/51] 8164748: Edit pad crashes when calling function Reviewed-by: jlaskey --- .../share/classes/jdk/nashorn/tools/jjs/Main.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Main.java b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Main.java index 418bce95c85..d792738cfa4 100644 --- a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Main.java +++ b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Main.java @@ -172,7 +172,7 @@ public final class Main extends Shell { final Consumer evaluator = str -> { // could be called from different thread (GUI), we need to handle Context set/reset final Global _oldGlobal = Context.getGlobal(); - final boolean _globalChanged = (oldGlobal != global); + final boolean _globalChanged = (_oldGlobal != global); if (_globalChanged) { Context.setGlobal(global); } From 83c2e4ef3c38007fa4673804599cc5eab5596378 Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Thu, 25 Aug 2016 15:06:26 -0400 Subject: [PATCH 28/51] 8151893: Add security property to configure XML Signature secure validation mode Reviewed-by: jnimeh, xuelei --- .../share/conf/security/java.security | 41 ++++ .../share/lib/security/default.policy | 2 + .../dsig/internal/dom/ApacheTransform.java | 5 +- .../xml/dsig/internal/dom/DOMManifest.java | 9 +- .../xml/dsig/internal/dom/DOMReference.java | 21 +-- .../dsig/internal/dom/DOMRetrievalMethod.java | 12 +- .../xml/dsig/internal/dom/DOMSignedInfo.java | 29 +-- .../dsig/internal/dom/DOMURIDereferencer.java | 24 ++- .../org/jcp/xml/dsig/internal/dom/Policy.java | 178 ++++++++++++++++++ .../crypto/dsig/SecureValidationPolicy.java | 72 +++++++ 10 files changed, 341 insertions(+), 52 deletions(-) create mode 100644 jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java create mode 100644 jdk/test/javax/xml/crypto/dsig/SecureValidationPolicy.java diff --git a/jdk/src/java.base/share/conf/security/java.security b/jdk/src/java.base/share/conf/security/java.security index 2bba767dd05..4f668d466a7 100644 --- a/jdk/src/java.base/share/conf/security/java.security +++ b/jdk/src/java.base/share/conf/security/java.security @@ -803,3 +803,44 @@ jdk.tls.legacyAlgorithms= \ # E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED \ # EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \ # FFFFFFFF FFFFFFFF, 2} + +# +# The policy for the XML Signature secure validation mode. The mode is +# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to +# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method, +# or by running the code with a SecurityManager. +# +# Policy: +# Constraint {"," Constraint } +# Constraint: +# AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint | +# ReferenceUriSchemeConstraint | OtherConstraint +# AlgConstraint +# "disallowAlg" Uri +# MaxTransformsConstraint: +# "maxTransforms" Integer +# MaxReferencesConstraint: +# "maxReferences" Integer +# ReferenceUriSchemeConstraint: +# "disallowReferenceUriSchemes" String { String } +# OtherConstraint: +# "noDuplicateIds" | "noRetrievalMethodLoops" +# +# For AlgConstraint, Uri is the algorithm URI String that is not allowed. +# See the XML Signature Recommendation for more information on algorithm +# URI Identifiers. If the MaxTransformsConstraint or MaxReferencesConstraint is +# specified more than once, only the last entry is enforced. +# +# Note: This property is currently used by the JDK Reference implementation. It +# is not guaranteed to be examined and used by other implementations. +# +jdk.xml.dsig.secureValidationPolicy=\ + disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\ + maxTransforms 5,\ + maxReferences 30,\ + disallowReferenceUriSchemes file http https,\ + noDuplicateIds,\ + noRetrievalMethodLoops diff --git a/jdk/src/java.base/share/lib/security/default.policy b/jdk/src/java.base/share/lib/security/default.policy index 318bd8bb2ab..f57e67fb482 100644 --- a/jdk/src/java.base/share/lib/security/default.policy +++ b/jdk/src/java.base/share/lib/security/default.policy @@ -72,6 +72,8 @@ grant codeBase "jrt:/java.xml.crypto" { "removeProviderProperty.XMLDSig"; permission java.security.SecurityPermission "com.sun.org.apache.xml.internal.security.register"; + permission java.security.SecurityPermission + "getProperty.jdk.xml.dsig.secureValidationPolicy"; }; grant codeBase "jrt:/java.xml.ws" { diff --git a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java index 3cad0fd6f0c..c053df02a7f 100644 --- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java +++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java @@ -21,7 +21,7 @@ * under the License. */ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * $Id: ApacheTransform.java 1333869 2012-05-04 10:42:44Z coheigea $ @@ -38,7 +38,6 @@ import org.w3c.dom.Node; import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; import com.sun.org.apache.xml.internal.security.transforms.Transform; -import com.sun.org.apache.xml.internal.security.transforms.Transforms; import javax.xml.crypto.*; import javax.xml.crypto.dom.DOMCryptoContext; @@ -150,7 +149,7 @@ public abstract class ApacheTransform extends TransformService { if (Utils.secureValidation(xc)) { String algorithm = getAlgorithm(); - if (Transforms.TRANSFORM_XSLT.equals(algorithm)) { + if (Policy.restrictAlg(algorithm)) { throw new TransformException( "Transform " + algorithm + " is forbidden when secure validation is enabled" ); diff --git a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java index 2c86d8f65ee..69a2a3371c8 100644 --- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java +++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java @@ -21,7 +21,7 @@ * under the License. */ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * $Id: DOMManifest.java 1333415 2012-05-03 12:03:51Z coheigea $ @@ -110,9 +110,10 @@ public final class DOMManifest extends DOMStructure implements Manifest { localName + ", expected Reference"); } refs.add(new DOMReference(refElem, context, provider)); - if (secVal && (refs.size() > DOMSignedInfo.MAXIMUM_REFERENCE_COUNT)) { - String error = "A maxiumum of " + DOMSignedInfo.MAXIMUM_REFERENCE_COUNT + " " - + "references per Manifest are allowed with secure validation"; + if (secVal && Policy.restrictNumReferences(refs.size())) { + String error = "A maximum of " + Policy.maxReferences() + + " references per Manifest are allowed when" + + " secure validation is enabled"; throw new MarshalException(error); } refElem = DOMUtils.getNextSiblingElement(refElem); diff --git a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java index 91f9054657a..7e2f33129db 100644 --- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java +++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java @@ -21,7 +21,7 @@ * under the License. */ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * =========================================================================== @@ -51,7 +51,6 @@ import org.w3c.dom.Element; import org.w3c.dom.Node; import org.jcp.xml.dsig.internal.DigesterOutputStream; -import com.sun.org.apache.xml.internal.security.algorithms.MessageDigestAlgorithm; import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException; import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; import com.sun.org.apache.xml.internal.security.utils.Base64; @@ -66,11 +65,6 @@ import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream public final class DOMReference extends DOMStructure implements Reference, DOMURIReference { - /** - * The maximum number of transforms per reference, if secure validation is enabled. - */ - public static final int MAXIMUM_TRANSFORM_COUNT = 5; - /** * Look up useC14N11 system property. If true, an explicit C14N11 transform * will be added if necessary when generating the signature. See section @@ -208,9 +202,10 @@ public final class DOMReference extends DOMStructure } transforms.add (new DOMTransform(transformElem, context, provider)); - if (secVal && (transforms.size() > MAXIMUM_TRANSFORM_COUNT)) { - String error = "A maxiumum of " + MAXIMUM_TRANSFORM_COUNT + " " - + "transforms per Reference are allowed with secure validation"; + if (secVal && Policy.restrictNumTransforms(transforms.size())) { + String error = "A maximum of " + Policy.maxTransforms() + + " transforms per Reference are allowed when" + + " secure validation is enabled"; throw new MarshalException(error); } transformElem = DOMUtils.getNextSiblingElement(transformElem); @@ -227,10 +222,10 @@ public final class DOMReference extends DOMStructure Element dmElem = nextSibling; this.digestMethod = DOMDigestMethod.unmarshal(dmElem); String digestMethodAlgorithm = this.digestMethod.getAlgorithm(); - if (secVal - && MessageDigestAlgorithm.ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5.equals(digestMethodAlgorithm)) { + if (secVal && Policy.restrictAlg(digestMethodAlgorithm)) { throw new MarshalException( - "It is forbidden to use algorithm " + digestMethod + " when secure validation is enabled" + "It is forbidden to use algorithm " + digestMethodAlgorithm + + " when secure validation is enabled" ); } diff --git a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java index eed6fffe5a5..d5ac8c16dbc 100644 --- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java +++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java @@ -21,7 +21,7 @@ * under the License. */ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * =========================================================================== @@ -149,9 +149,10 @@ public final class DOMRetrievalMethod extends DOMStructure } transforms.add (new DOMTransform(transformElem, context, provider)); - if (secVal && (transforms.size() > DOMReference.MAXIMUM_TRANSFORM_COUNT)) { - String error = "A maxiumum of " + DOMReference.MAXIMUM_TRANSFORM_COUNT + " " - + "transforms per Reference are allowed with secure validation"; + if (secVal && Policy.restrictNumTransforms(transforms.size())) { + String error = "A maximum of " + Policy.maxTransforms() + + " transforms per Reference are allowed when" + + " secure validation is enabled"; throw new MarshalException(error); } transformElem = DOMUtils.getNextSiblingElement(transformElem); @@ -238,7 +239,8 @@ public final class DOMRetrievalMethod extends DOMStructure } // guard against RetrievalMethod loops - if ((data instanceof NodeSetData) && Utils.secureValidation(context)) { + if ((data instanceof NodeSetData) && Utils.secureValidation(context) + && Policy.restrictRetrievalMethodLoops()) { NodeSetData nsd = (NodeSetData)data; Iterator i = nsd.iterator(); if (i.hasNext()) { diff --git a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java index c18a462fba7..17043b4c165 100644 --- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java +++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java @@ -21,7 +21,7 @@ * under the License. */ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * $Id: DOMSignedInfo.java 1333415 2012-05-03 12:03:51Z coheigea $ @@ -45,7 +45,6 @@ import org.w3c.dom.Element; import org.w3c.dom.Node; import com.sun.org.apache.xml.internal.security.utils.Base64; -import com.sun.org.apache.xml.internal.security.utils.Constants; import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream; /** @@ -55,22 +54,9 @@ import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream */ public final class DOMSignedInfo extends DOMStructure implements SignedInfo { - /** - * The maximum number of references per Manifest, if secure validation is enabled. - */ - public static final int MAXIMUM_REFERENCE_COUNT = 30; - private static java.util.logging.Logger log = java.util.logging.Logger.getLogger("org.jcp.xml.dsig.internal.dom"); - /** Signature - NOT Recommended RSAwithMD5 */ - private static final String ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5 = - Constants.MoreAlgorithmsSpecNS + "rsa-md5"; - - /** HMAC - NOT Recommended HMAC-MD5 */ - private static final String ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5 = - Constants.MoreAlgorithmsSpecNS + "hmac-md5"; - private List references; private CanonicalizationMethod canonicalizationMethod; private SignatureMethod signatureMethod; @@ -158,10 +144,10 @@ public final class DOMSignedInfo extends DOMStructure implements SignedInfo { boolean secVal = Utils.secureValidation(context); String signatureMethodAlgorithm = signatureMethod.getAlgorithm(); - if (secVal && ((ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5.equals(signatureMethodAlgorithm) - || ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5.equals(signatureMethodAlgorithm)))) { + if (secVal && Policy.restrictAlg(signatureMethodAlgorithm)) { throw new MarshalException( - "It is forbidden to use algorithm " + signatureMethod + " when secure validation is enabled" + "It is forbidden to use algorithm " + signatureMethodAlgorithm + + " when secure validation is enabled" ); } @@ -179,9 +165,10 @@ public final class DOMSignedInfo extends DOMStructure implements SignedInfo { } refList.add(new DOMReference(refElem, context, provider)); - if (secVal && (refList.size() > MAXIMUM_REFERENCE_COUNT)) { - String error = "A maxiumum of " + MAXIMUM_REFERENCE_COUNT + " " - + "references per Manifest are allowed with secure validation"; + if (secVal && Policy.restrictNumReferences(refList.size())) { + String error = "A maximum of " + Policy.maxReferences() + + " references per Manifest are allowed when" + + " secure validation is enabled"; throw new MarshalException(error); } refElem = DOMUtils.getNextSiblingElement(refElem); diff --git a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java index d2beb4e50a6..72791df3a2a 100644 --- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java +++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java @@ -21,7 +21,7 @@ * under the License. */ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * $Id: DOMURIDereferencer.java 1231033 2012-01-13 12:12:12Z coheigea $ @@ -73,6 +73,11 @@ public class DOMURIDereferencer implements URIDereferencer { boolean secVal = Utils.secureValidation(context); + if (secVal && Policy.restrictReferenceUriScheme(uri)) { + throw new URIReferenceException( + "Uri " + uri + " is forbidden when secure validation is enabled"); + } + // Check if same-document URI and already registered on the context if (uri != null && uri.length() != 0 && uri.charAt(0) == '#') { String id = uri.substring(1); @@ -83,12 +88,19 @@ public class DOMURIDereferencer implements URIDereferencer { id = id.substring(i1+1, i2); } - Node referencedElem = dcc.getElementById(id); + // check if element is registered by Id + Node referencedElem = uriAttr.getOwnerDocument().getElementById(id); + if (referencedElem == null) { + // see if element is registered in DOMCryptoContext + referencedElem = dcc.getElementById(id); + } if (referencedElem != null) { - if (secVal) { + if (secVal && Policy.restrictDuplicateIds()) { Element start = referencedElem.getOwnerDocument().getDocumentElement(); if (!XMLUtils.protectAgainstWrappingAttack(start, (Element)referencedElem, id)) { - String error = "Multiple Elements with the same ID " + id + " were detected"; + String error = "Multiple Elements with the same ID " + + id + " detected when secure validation" + + " is enabled"; throw new URIReferenceException(error); } } @@ -110,9 +122,9 @@ public class DOMURIDereferencer implements URIDereferencer { try { ResourceResolver apacheResolver = - ResourceResolver.getInstance(uriAttr, baseURI, secVal); + ResourceResolver.getInstance(uriAttr, baseURI, false); XMLSignatureInput in = apacheResolver.resolve(uriAttr, - baseURI, secVal); + baseURI, false); if (in.isOctetStream()) { return new ApacheOctetStreamData(in); } else { diff --git a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java new file mode 100644 index 00000000000..af9bea40876 --- /dev/null +++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.jcp.xml.dsig.internal.dom; + +import java.net.URI; +import java.net.URISyntaxException; +import java.security.AccessController; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.Security; +import java.util.Collections; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; + +/** + * The secure validation policy as specified by the + * jdk.xml.dsig.secureValidationPolicy security property. + */ +public final class Policy { + + // all restrictions are initialized to be unconstrained + private static Set disallowedAlgs = new HashSet<>(); + private static int maxTrans = Integer.MAX_VALUE; + private static int maxRefs = Integer.MAX_VALUE; + private static Set disallowedRefUriSchemes = new HashSet<>(); + private static boolean noDuplicateIds = false; + private static boolean noRMLoops = false; + + static { + try { + initialize(); + } catch (Exception e) { + throw new SecurityException( + "Cannot initialize the secure validation policy", e); + } + } + + private Policy() {} + + private static void initialize() { + String prop = + AccessController.doPrivileged((PrivilegedAction) () -> + Security.getProperty("jdk.xml.dsig.secureValidationPolicy")); + if (prop == null || prop.isEmpty()) { + // no policy specified, so don't enforce any restrictions + return; + } + String[] entries = prop.split(","); + for (String entry : entries) { + String[] tokens = entry.split("\\s"); + String type = tokens[0]; + switch(type) { + case "disallowAlg": + if (tokens.length != 2) { + error(entry); + } + disallowedAlgs.add(URI.create(tokens[1])); + break; + case "maxTransforms": + if (tokens.length != 2) { + error(entry); + } + maxTrans = Integer.parseUnsignedInt(tokens[1]); + break; + case "maxReferences": + if (tokens.length != 2) { + error(entry); + } + maxRefs = Integer.parseUnsignedInt(tokens[1]); + break; + case "disallowReferenceUriSchemes": + if (tokens.length == 1) { + error(entry); + } + for (int i = 1; i < tokens.length; i++) { + String scheme = tokens[i]; + disallowedRefUriSchemes.add( + scheme.toLowerCase(Locale.ROOT)); + } + break; + case "noDuplicateIds": + if (tokens.length != 1) { + error(entry); + } + noDuplicateIds = true; + break; + case "noRetrievalMethodLoops": + if (tokens.length != 1) { + error(entry); + } + noRMLoops = true; + break; + default: + error(entry); + } + } + } + + public static boolean restrictAlg(String alg) { + try { + URI uri = new URI(alg); + return disallowedAlgs.contains(uri); + } catch (URISyntaxException use) { + return false; + } + } + + public static boolean restrictNumTransforms(int numTrans) { + return (numTrans > maxTrans); + } + + public static boolean restrictNumReferences(int numRefs) { + return (numRefs > maxRefs); + } + + public static boolean restrictReferenceUriScheme(String uri) { + if (uri != null) { + String scheme = java.net.URI.create(uri).getScheme(); + if (scheme != null) { + return disallowedRefUriSchemes.contains( + scheme.toLowerCase(Locale.ROOT)); + } + } + return false; + } + + public static boolean restrictDuplicateIds() { + return noDuplicateIds; + } + + public static boolean restrictRetrievalMethodLoops() { + return noRMLoops; + } + + public static Set disabledAlgs() { + return Collections.unmodifiableSet(disallowedAlgs); + } + + public static int maxTransforms() { + return maxTrans; + } + + public static int maxReferences() { + return maxRefs; + } + + public static Set disabledReferenceUriSchemes() { + return Collections.unmodifiableSet(disallowedRefUriSchemes); + } + + private static void error(String entry) { + throw new IllegalArgumentException( + "Invalid jdk.xml.dsig.secureValidationPolicy entry: " + entry); + } +} diff --git a/jdk/test/javax/xml/crypto/dsig/SecureValidationPolicy.java b/jdk/test/javax/xml/crypto/dsig/SecureValidationPolicy.java new file mode 100644 index 00000000000..53642c02bcf --- /dev/null +++ b/jdk/test/javax/xml/crypto/dsig/SecureValidationPolicy.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8151893 + * @summary Tests for the jdk.xml.dsig.secureValidationPolicy security property + * @modules java.xml.crypto/org.jcp.xml.dsig.internal.dom + */ + +import java.security.Security; +import java.util.List; +import org.jcp.xml.dsig.internal.dom.Policy; + +public class SecureValidationPolicy { + + public static void main(String[] args) throws Exception { + + List restrictedSchemes = List.of("file:/tmp/foo", + "http://java.com", "https://java.com"); + List restrictedAlgs = List.of( + "http://www.w3.org/TR/1999/REC-xslt-19991116", + "http://www.w3.org/2001/04/xmldsig-more#rsa-md5", + "http://www.w3.org/2001/04/xmldsig-more#hmac-md5", + "http://www.w3.org/2001/04/xmldsig-more#md5"); + + // Test expected defaults + System.out.println("Testing defaults"); + if (!Policy.restrictNumTransforms(6)) { + throw new Exception("maxTransforms not enforced"); + } + if (!Policy.restrictNumReferences(31)) { + throw new Exception("maxReferences not enforced"); + } + for (String scheme : restrictedSchemes) { + if (!Policy.restrictReferenceUriScheme(scheme)) { + throw new Exception(scheme + " scheme not restricted"); + } + } + for (String alg : restrictedAlgs) { + if (!Policy.restrictAlg(alg)) { + throw new Exception(alg + " alg not restricted"); + } + } + if (!Policy.restrictDuplicateIds()) { + throw new Exception("noDuplicateIds not enforced"); + } + if (!Policy.restrictRetrievalMethodLoops()) { + throw new Exception("noRetrievalMethodLoops not enforced"); + } + } +} From c2f0a9479fcd7bba2b22446ed5727ce87cf69799 Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Thu, 25 Aug 2016 17:08:15 -0400 Subject: [PATCH 29/51] 8150158: Update bugs.sun.com references to bugs.java.com Reviewed-by: ascarpino --- .../security/algorithms/implementations/IntegrityHmac.java | 2 +- .../security/algorithms/implementations/SignatureBaseRSA.java | 2 +- .../security/algorithms/implementations/SignatureDSA.java | 2 +- .../security/algorithms/implementations/SignatureECDSA.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java index 8935e389728..94eae3b772e 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java @@ -150,7 +150,7 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi { this.macAlgorithm.init(secretKey); } catch (InvalidKeyException ex) { // reinstantiate Mac object to work around bug in JDK - // see: http://bugs.sun.com/view_bug.do?bug_id=4953555 + // see: http://bugs.java.com/view_bug.do?bug_id=4953555 Mac mac = this.macAlgorithm; try { this.macAlgorithm = Mac.getInstance(macAlgorithm.getAlgorithm()); diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java index 7460f66ffd6..f7d169572e2 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java @@ -112,7 +112,7 @@ public abstract class SignatureBaseRSA extends SignatureAlgorithmSpi { this.signatureAlgorithm.initVerify((PublicKey) publicKey); } catch (InvalidKeyException ex) { // reinstantiate Signature object to work around bug in JDK - // see: http://bugs.sun.com/view_bug.do?bug_id=4953555 + // see: http://bugs.java.com/view_bug.do?bug_id=4953555 Signature sig = this.signatureAlgorithm; try { this.signatureAlgorithm = Signature.getInstance(signatureAlgorithm.getAlgorithm()); diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java index 7a771d71beb..6638e9293e4 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java @@ -139,7 +139,7 @@ public class SignatureDSA extends SignatureAlgorithmSpi { this.signatureAlgorithm.initVerify((PublicKey) publicKey); } catch (InvalidKeyException ex) { // reinstantiate Signature object to work around bug in JDK - // see: http://bugs.sun.com/view_bug.do?bug_id=4953555 + // see: http://bugs.java.com/view_bug.do?bug_id=4953555 Signature sig = this.signatureAlgorithm; try { this.signatureAlgorithm = Signature.getInstance(signatureAlgorithm.getAlgorithm()); diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java index 8da7a8c6e67..7ba65724fb0 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java @@ -252,7 +252,7 @@ public abstract class SignatureECDSA extends SignatureAlgorithmSpi { this.signatureAlgorithm.initVerify((PublicKey) publicKey); } catch (InvalidKeyException ex) { // reinstantiate Signature object to work around bug in JDK - // see: http://bugs.sun.com/view_bug.do?bug_id=4953555 + // see: http://bugs.java.com/view_bug.do?bug_id=4953555 Signature sig = this.signatureAlgorithm; try { this.signatureAlgorithm = Signature.getInstance(signatureAlgorithm.getAlgorithm()); From 163f2f0e0242515a6088fa13050d348377439c13 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 25 Aug 2016 21:18:46 +0000 Subject: [PATCH 30/51] Added tag jdk-9+133 for changeset 77232505c496 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index d0c1a581878..4639f93e55b 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -375,3 +375,4 @@ c40c8739bcdc88892ff58ebee3fd8a3f287be94d jdk-9+123 6c827500e34587061af97ad6fef0e859280255c5 jdk-9+130 8c57f4c293bbc5609928308a6d91ba765760b5f9 jdk-9+131 d5c70818cd8a82e76632c8c815bdb4f75f53aeaf jdk-9+132 +3cdae27c90b5e41afe75eab904fda19fac076330 jdk-9+133 From db470fad5dedbe40b2df942ac46246d2f9736e65 Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Thu, 25 Aug 2016 17:58:49 -0700 Subject: [PATCH 31/51] 8164698: modify jdk makefiles to build jdeprscan Reviewed-by: psandoz --- jdk/make/launcher/Launcher-jdk.jdeps.gmk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/jdk/make/launcher/Launcher-jdk.jdeps.gmk b/jdk/make/launcher/Launcher-jdk.jdeps.gmk index 6cbcaf47163..4a69deede07 100644 --- a/jdk/make/launcher/Launcher-jdk.jdeps.gmk +++ b/jdk/make/launcher/Launcher-jdk.jdeps.gmk @@ -36,3 +36,9 @@ $(eval $(call SetupBuildLauncher, jdeps, \ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \ )) + +$(eval $(call SetupBuildLauncher, jdeprscan, \ + MAIN_CLASS := com.sun.tools.jdeprscan.Main, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \ + -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \ +)) From 736833a357831d674531a83b7364032fc92f9be8 Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Thu, 25 Aug 2016 21:58:38 -0700 Subject: [PATCH 32/51] 8164834: remove jdeprscan from tools/launcher/VersionCheck.java Reviewed-by: sundar, darcy --- jdk/test/tools/launcher/VersionCheck.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/test/tools/launcher/VersionCheck.java b/jdk/test/tools/launcher/VersionCheck.java index 10fce9781f9..afbde0782a3 100644 --- a/jdk/test/tools/launcher/VersionCheck.java +++ b/jdk/test/tools/launcher/VersionCheck.java @@ -82,6 +82,7 @@ public class VersionCheck extends TestHelper { "jcmd", "jconsole", "jcontrol", + "jdeprscan", "jdeps", "jimage", "jinfo", From ab6aaea20ada639f5c419be9940f5dc61602653d Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Fri, 26 Aug 2016 11:50:36 +0530 Subject: [PATCH 33/51] 8147491: module graph consistency checks after jlink plugins operate on module pool Reviewed-by: jlaskey, mchung, psandoz --- .../jlink/internal/ImagePluginStack.java | 17 ++- .../internal/ResourcePoolConfiguration.java | 128 ++++++++++++++++++ jdk/test/tools/jlink/CustomPluginTest.java | 44 +++++- .../tools/jlink/ImageFileCreatorTest.java | 2 +- .../tools/jlink/customplugin/module-info.java | 2 + .../customplugin/plugin/RogueAdderPlugin.java | 76 +++++++++++ .../plugin/RogueFilterPlugin.java | 74 ++++++++++ 7 files changed, 338 insertions(+), 5 deletions(-) create mode 100644 jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolConfiguration.java create mode 100644 jdk/test/tools/jlink/customplugin/plugin/RogueAdderPlugin.java create mode 100644 jdk/test/tools/jlink/customplugin/plugin/RogueFilterPlugin.java diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java index a0b91d33473..5ec8f67948f 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java @@ -172,7 +172,7 @@ public final class ImagePluginStack { private final Plugin lastSorter; private final List plugins = new ArrayList<>(); private final List resourcePrevisitors = new ArrayList<>(); - + private final boolean validate; public ImagePluginStack() { this(null, Collections.emptyList(), null); @@ -181,6 +181,13 @@ public final class ImagePluginStack { public ImagePluginStack(ImageBuilder imageBuilder, List plugins, Plugin lastSorter) { + this(imageBuilder, plugins, lastSorter, true); + } + + public ImagePluginStack(ImageBuilder imageBuilder, + List plugins, + Plugin lastSorter, + boolean validate) { this.imageBuilder = Objects.requireNonNull(imageBuilder); this.lastSorter = lastSorter; this.plugins.addAll(Objects.requireNonNull(plugins)); @@ -190,6 +197,7 @@ public final class ImagePluginStack { resourcePrevisitors.add((ResourcePrevisitor) p); } }); + this.validate = validate; } public void operate(ImageProvider provider) throws Exception { @@ -268,6 +276,7 @@ public final class ImagePluginStack { frozenOrder = ((OrderedResourcePoolManager.OrderedResourcePool)resPool).getOrderedList(); } } + return resPool; } @@ -458,7 +467,11 @@ public final class ImagePluginStack { throws Exception { Objects.requireNonNull(original); Objects.requireNonNull(transformed); - imageBuilder.storeFiles(new LastPoolManager(transformed).resourcePool()); + ResourcePool lastPool = new LastPoolManager(transformed).resourcePool(); + if (validate) { + ResourcePoolConfiguration.validate(lastPool); + } + imageBuilder.storeFiles(lastPool); } public ExecutableImage getExecutableImage() throws IOException { diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolConfiguration.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolConfiguration.java new file mode 100644 index 00000000000..11af53af6c1 --- /dev/null +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolConfiguration.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jlink.internal; + +import java.lang.module.Configuration; +import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleFinder; +import java.lang.module.ModuleReference; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.ByteBuffer; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import jdk.tools.jlink.plugin.PluginException; +import jdk.tools.jlink.plugin.ResourcePool; +import jdk.tools.jlink.plugin.ResourcePoolEntry; +import jdk.tools.jlink.plugin.ResourcePoolModule; + +final class ResourcePoolConfiguration { + private ResourcePoolConfiguration() {} + + private static ModuleDescriptor descriptorOf(ResourcePoolModule mod) { + ModuleDescriptor md = mod.descriptor(); + + // drop hashes + ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(md.name()); + md.requires().stream() + .forEach(builder::requires); + md.exports().stream() + .forEach(builder::exports); + md.uses().stream() + .forEach(builder::uses); + md.provides().values().stream() + .forEach(builder::provides); + + // build the proper concealed packages + Set exps = md.exports().stream() + .map(ModuleDescriptor.Exports::source) + .collect(Collectors.toSet()); + + mod.packages().stream() + .filter(pn -> !exps.contains(pn)) + .forEach(builder::conceals); + + md.version().ifPresent(builder::version); + md.mainClass().ifPresent(builder::mainClass); + md.osName().ifPresent(builder::osName); + md.osArch().ifPresent(builder::osArch); + md.osVersion().ifPresent(builder::osVersion); + + return builder.build(); + } + + private static ModuleReference moduleReference(ModuleDescriptor desc) { + return new ModuleReference(desc, null, () -> { + IOException ioe = new IOException(""); + throw new UncheckedIOException(ioe); + }); + } + + private static Map allModRefs(ResourcePool pool) { + return pool.moduleView().modules(). + collect(Collectors.toMap(ResourcePoolModule::name, + m -> moduleReference(descriptorOf(m)))); + } + + private static void checkPackages(ResourcePool pool) { + // check that each resource pool module's packages() + // returns a set that is consistent with the module + // descriptor of that module. + + pool.moduleView().modules().forEach(m -> { + ModuleDescriptor desc = m.descriptor(); + if (!desc.packages().equals(m.packages())) { + throw new RuntimeException("Module " + m.name() + + "'s descriptor returns inconsistent package set"); + } + }); + } + + static Configuration validate(ResourcePool pool) { + checkPackages(pool); + final Map nameToModRef = allModRefs(pool); + final Set allRefs = new HashSet<>(nameToModRef.values()); + + final ModuleFinder finder = new ModuleFinder() { + @Override + public Optional find(String name) { + return Optional.ofNullable(nameToModRef.get(name)); + } + + @Override + public Set findAll() { + return allRefs; + } + }; + + return Configuration.empty().resolveRequires( + finder, ModuleFinder.of(), nameToModRef.keySet()); + } +} diff --git a/jdk/test/tools/jlink/CustomPluginTest.java b/jdk/test/tools/jlink/CustomPluginTest.java index dc7a774ca51..aef3ace833e 100644 --- a/jdk/test/tools/jlink/CustomPluginTest.java +++ b/jdk/test/tools/jlink/CustomPluginTest.java @@ -67,6 +67,7 @@ public class CustomPluginTest { testHelloProvider(helper, pluginModulePath); testCustomPlugins(helper, pluginModulePath); + testModuleVerification(helper, pluginModulePath); } private void testCustomPlugins(Helper helper, Path pluginModulePath) { @@ -93,8 +94,7 @@ public class CustomPluginTest { String name = "customplugin"; Path src = Paths.get(System.getProperty("test.src")).resolve(name); Path classes = helper.getJmodClassesDir().resolve(name); - JImageGenerator.compile(src, classes, - "--add-exports", "jdk.jlink/jdk.tools.jlink.internal=customplugin"); + JImageGenerator.compile(src, classes); return JImageGenerator.getJModTask() .addClassPath(classes) .jmod(helper.getJmodDir().resolve(name + ".jmod")) @@ -136,4 +136,44 @@ public class CustomPluginTest { throw new AssertionError("Custom plugin not called"); } } + + private void testModuleVerification(Helper helper, Path pluginModulePath) throws IOException { + { + // dependent module missing check + String moduleName = "bar"; // 8147491 + Path jmodFoo = helper.generateDefaultJModule("foo").assertSuccess(); + Path jmodBar = helper.generateDefaultJModule(moduleName, "foo").assertSuccess(); + // rogue filter removes "foo" module resources which are + // required by "bar" module. Module checks after plugin + // application should detect and report error. + JImageGenerator.getJLinkTask() + .modulePath(helper.defaultModulePath()) + .pluginModulePath(pluginModulePath) + .output(helper.createNewImageDir(moduleName)) + .addMods(moduleName) + .option("--rogue-filter") + .option("/foo/") + .call() + .assertFailure("java.lang.module.ResolutionException"); + } + + { + // package exported by one module used as concealed package + // in another module. But, module-info.class is not updated! + String moduleName = "jdk.scripting.nashorn"; + JImageGenerator.getJLinkTask() + .modulePath(helper.defaultModulePath()) + .pluginModulePath(pluginModulePath) + .output(helper.createNewImageDir(moduleName)) + .addMods(moduleName) + // "java.logging" includes a package 'javax.script' + // which is an exported package from "java.scripting" module! + // module-info.class of java.logging left "as is". + .option("--rogue-adder") + .option("/java.logging/javax/script/Foo.class") + .call() + .assertFailure( + "Module java.logging's descriptor returns inconsistent package set"); + } + } } diff --git a/jdk/test/tools/jlink/ImageFileCreatorTest.java b/jdk/test/tools/jlink/ImageFileCreatorTest.java index 694bd898045..c88ae4bada1 100644 --- a/jdk/test/tools/jlink/ImageFileCreatorTest.java +++ b/jdk/test/tools/jlink/ImageFileCreatorTest.java @@ -220,7 +220,7 @@ public class ImageFileCreatorTest { }; ImagePluginStack stack = new ImagePluginStack(noopBuilder, Collections.emptyList(), - null); + null, false); ImageFileCreator.create(archives, ByteOrder.nativeOrder(), stack); } diff --git a/jdk/test/tools/jlink/customplugin/module-info.java b/jdk/test/tools/jlink/customplugin/module-info.java index 4b51ff86769..b2d9f237668 100644 --- a/jdk/test/tools/jlink/customplugin/module-info.java +++ b/jdk/test/tools/jlink/customplugin/module-info.java @@ -25,4 +25,6 @@ module customplugin { requires jdk.jlink; provides jdk.tools.jlink.plugin.Plugin with plugin.HelloPlugin; provides jdk.tools.jlink.plugin.Plugin with plugin.CustomPlugin; + provides jdk.tools.jlink.plugin.Plugin with plugin.RogueAdderPlugin; + provides jdk.tools.jlink.plugin.Plugin with plugin.RogueFilterPlugin; } diff --git a/jdk/test/tools/jlink/customplugin/plugin/RogueAdderPlugin.java b/jdk/test/tools/jlink/customplugin/plugin/RogueAdderPlugin.java new file mode 100644 index 00000000000..fe78a642940 --- /dev/null +++ b/jdk/test/tools/jlink/customplugin/plugin/RogueAdderPlugin.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package plugin; + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.lang.module.ModuleDescriptor; +import java.util.Collections; +import java.util.Map; +import java.util.function.Function; +import jdk.tools.jlink.plugin.ResourcePool; +import jdk.tools.jlink.plugin.ResourcePoolBuilder; +import jdk.tools.jlink.plugin.ResourcePoolEntry; +import jdk.tools.jlink.plugin.ResourcePoolModule; +import jdk.tools.jlink.plugin.Plugin; + +/** + * Rogue adder plugin + */ +public final class RogueAdderPlugin implements Plugin { + public static final String NAME = "rogue-adder"; + private String resName; + + @Override + public String getName() { + return NAME; + } + + @Override + public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) { + in.transformAndCopy(Function.identity(), out); + out.add(ResourcePoolEntry.create(resName, new byte[1])); + return out.build(); + } + + @Override + public String getDescription() { + return NAME + "-description"; + } + + @Override + public Category getType() { + return Category.FILTER; + } + + @Override + public boolean hasArguments() { + return true; + } + + @Override + public void configure(Map config) { + resName = config.get(NAME); + } +} diff --git a/jdk/test/tools/jlink/customplugin/plugin/RogueFilterPlugin.java b/jdk/test/tools/jlink/customplugin/plugin/RogueFilterPlugin.java new file mode 100644 index 00000000000..ae4bf3f8183 --- /dev/null +++ b/jdk/test/tools/jlink/customplugin/plugin/RogueFilterPlugin.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package plugin; + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.Collections; +import java.util.Map; +import jdk.tools.jlink.plugin.ResourcePoolEntry; +import jdk.tools.jlink.plugin.ResourcePool; +import jdk.tools.jlink.plugin.ResourcePoolBuilder; +import jdk.tools.jlink.plugin.Plugin; + +/** + * Rogue filter plugin + */ +public final class RogueFilterPlugin implements Plugin { + public static final String NAME = "rogue-filter"; + private String prefix; + + @Override + public String getName() { + return NAME; + } + + @Override + public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) { + in.transformAndCopy((file) -> { + return file.path().startsWith(prefix)? null : file; + }, out); + return out.build(); + } + + @Override + public String getDescription() { + return NAME + "-description"; + } + + @Override + public Category getType() { + return Category.FILTER; + } + + @Override + public boolean hasArguments() { + return true; + } + + @Override + public void configure(Map config) { + prefix = config.get(NAME); + } +} From 6ab4f9a732acd1184a4e4d497f340e7c8fec2ecc Mon Sep 17 00:00:00 2001 From: Sibabrata Sahoo Date: Fri, 26 Aug 2016 01:20:30 -0700 Subject: [PATCH 34/51] 8006690: sun/security/krb5/auto/BadKdc* tests fails intermittently Some of test for bad KDC failed intermittently Reviewed-by: weijun --- jdk/test/sun/security/krb5/auto/BadKdc1.java | 10 +++++----- jdk/test/sun/security/krb5/auto/BadKdc2.java | 10 +++++----- jdk/test/sun/security/krb5/auto/BadKdc4.java | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/jdk/test/sun/security/krb5/auto/BadKdc1.java b/jdk/test/sun/security/krb5/auto/BadKdc1.java index bc70c2a8b74..0ac77b60868 100644 --- a/jdk/test/sun/security/krb5/auto/BadKdc1.java +++ b/jdk/test/sun/security/krb5/auto/BadKdc1.java @@ -44,16 +44,16 @@ public class BadKdc1 { } BadKdc.go( - "121212222222(32){1,2}1222(32){1,2}", // 1 2 + "121212222222(32){1,3}1222(32){1,3}", // 1 2 // The above line means try kdc1 for 2 seconds then kdc1 // for 2 seconds... finally kdc3 for 2 seconds. - "1222(32){1,2}1222(32){1,2}", // 1 2 + "1222(32){1,3}1222(32){1,3}", // 1 2 // refresh - "121212222222(32){1,2}1222(32){1,2}", // 1 2 + "121212222222(32){1,3}1222(32){1,3}", // 1 2 // k3 off k2 on - "(122212(22){1,2}|1222323232-)", // 1 + "(122212(22){1,3}|1222323232-)", // 1 // k1 on - "(12(12){1,2}|122212|122232-)" // empty + "(12(12){1,3}|122212|122232-)" // empty ); } } diff --git a/jdk/test/sun/security/krb5/auto/BadKdc2.java b/jdk/test/sun/security/krb5/auto/BadKdc2.java index 4291d5c14c0..a490ca73c87 100644 --- a/jdk/test/sun/security/krb5/auto/BadKdc2.java +++ b/jdk/test/sun/security/krb5/auto/BadKdc2.java @@ -42,14 +42,14 @@ public class BadKdc2 { Security.setProperty( "krb5.kdc.bad.policy", "tryLess:2," + BadKdc.toReal(1000)); BadKdc.go( - "121212222222(32){1,2}11112121(32){1,2}", // 1 2 - "11112121(32){1,2}11112121(32){1,2}", // 1 2 + "121212222222(32){1,3}11112121(32){1,3}", // 1 2 + "11112121(32){1,3}11112121(32){1,3}", // 1 2 // refresh - "121212222222(32){1,2}11112121(32){1,2}", // 1 2 + "121212222222(32){1,3}11112121(32){1,3}", // 1 2 // k3 off k2 on - "1111(21){1,2}1111(22){1,2}", // 1 + "1111(21){1,3}1111(22){1,3}", // 1 // k1 on - "(11){1,2}(12){1,2}" // empty + "(11){1,3}(12){1,3}" // empty ); } } diff --git a/jdk/test/sun/security/krb5/auto/BadKdc4.java b/jdk/test/sun/security/krb5/auto/BadKdc4.java index 877e5400df9..8d64db2faca 100644 --- a/jdk/test/sun/security/krb5/auto/BadKdc4.java +++ b/jdk/test/sun/security/krb5/auto/BadKdc4.java @@ -37,12 +37,12 @@ public class BadKdc4 { throws Exception { Security.setProperty("krb5.kdc.bad.policy", ""); BadKdc.go( - "121212222222(32){1,2}121212222222(32){1,2}", - "121212222222(32){1,2}121212222222(32){1,2}", + "121212222222(32){1,3}121212222222(32){1,3}", + "121212222222(32){1,3}121212222222(32){1,3}", // refresh - "121212222222(32){1,2}121212222222(32){1,2}", + "121212222222(32){1,3}121212222222(32){1,3}", // k3 off k2 on - "121212(22){1,2}121212(22){1,2}", + "121212(22){1,3}121212(22){1,3}", // k1 on "(12){2,4}" ); From f78a742b53bcb27fce5792700816f074bdc9c5d9 Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Fri, 26 Aug 2016 08:16:42 -0400 Subject: [PATCH 35/51] 8024714: In java.security file, ocsp.responderCertSubjectName should not contain quotes Reviewed-by: vinnie --- jdk/src/java.base/share/conf/security/java.security | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.base/share/conf/security/java.security b/jdk/src/java.base/share/conf/security/java.security index 4f668d466a7..5154fd05a0f 100644 --- a/jdk/src/java.base/share/conf/security/java.security +++ b/jdk/src/java.base/share/conf/security/java.security @@ -490,7 +490,7 @@ networkaddress.cache.negative.ttl=10 # property is set then those two properties are ignored. # # Example, -# ocsp.responderCertSubjectName="CN=OCSP Responder, O=XYZ Corp" +# ocsp.responderCertSubjectName=CN=OCSP Responder, O=XYZ Corp # # Issuer name of the OCSP responder's certificate @@ -505,7 +505,7 @@ networkaddress.cache.negative.ttl=10 # property is ignored. # # Example, -# ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp" +# ocsp.responderCertIssuerName=CN=Enterprise CA, O=XYZ Corp # # Serial number of the OCSP responder's certificate From 1a404080eee49fa16c61ba9e7ac6e521779999e1 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Fri, 26 Aug 2016 16:16:09 +0200 Subject: [PATCH 36/51] 8163371: Enable tracing which JLI classes can be pre-generated Reviewed-by: vlivanov --- .../java/lang/invoke/BoundMethodHandle.java | 4 + .../lang/invoke/InvokerBytecodeGenerator.java | 5 +- .../java/lang/invoke/MethodHandleStatics.java | 3 + .../plugins/GenerateJLIClassesPlugin.java | 209 ++++++++++-------- .../tools/jlink/resources/plugins.properties | 6 +- 5 files changed, 127 insertions(+), 100 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java index 91071a2b3b4..461dd3967cb 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java @@ -497,6 +497,10 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; String shortTypes = LambdaForm.shortenSignature(types); String className = SPECIES_CLASS_PREFIX + shortTypes; Class c = BootLoader.loadClassOrNull(className); + if (TRACE_RESOLVE) { + System.out.println("[BMH_RESOLVE] " + shortTypes + + (c != null ? " (success)" : " (fail)") ); + } if (c != null) { return c.asSubclass(BoundMethodHandle.class); } else { diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index b71bd527608..afb04b6efa4 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -607,7 +607,10 @@ class InvokerBytecodeGenerator { private static MemberName resolveFrom(String name, MethodType type, Class holder) { MemberName member = new MemberName(holder, name, type, REF_invokeStatic); MemberName resolvedMember = MemberName.getFactory().resolveOrNull(REF_invokeStatic, member, holder); - + if (TRACE_RESOLVE) { + System.out.println("[LF_RESOLVE] " + holder.getName() + " " + name + " " + + shortenSignature(basicTypeSignature(type)) + (resolvedMember != null ? " (success)" : " (fail)") ); + } return resolvedMember; } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java index 4f5f1f4dc0d..22408f1b55a 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java @@ -46,6 +46,7 @@ import java.util.Properties; static final boolean DUMP_CLASS_FILES; static final boolean TRACE_INTERPRETER; static final boolean TRACE_METHOD_LINKAGE; + static final boolean TRACE_RESOLVE; static final int COMPILE_THRESHOLD; static final boolean LOG_LF_COMPILATION_FAILURE; static final int DONT_INLINE_THRESHOLD; @@ -65,6 +66,8 @@ import java.util.Properties; props.getProperty("java.lang.invoke.MethodHandle.TRACE_INTERPRETER")); TRACE_METHOD_LINKAGE = Boolean.parseBoolean( props.getProperty("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE")); + TRACE_RESOLVE = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.MethodHandle.TRACE_RESOLVE")); COMPILE_THRESHOLD = Integer.parseInt( props.getProperty("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", "0")); LOG_LF_COMPILATION_FAILURE = Boolean.parseBoolean( diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java index 514d1b7528e..42fe47c97f1 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java @@ -24,7 +24,11 @@ */ package jdk.tools.jlink.internal.plugins; +import java.io.File; +import java.io.IOException; import java.lang.invoke.MethodType; +import java.nio.file.Files; +import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; import java.util.HashMap; @@ -32,6 +36,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; import jdk.internal.misc.SharedSecrets; import jdk.internal.misc.JavaLangInvokeAccess; import jdk.tools.jlink.plugin.ResourcePoolEntry; @@ -47,12 +52,8 @@ public final class GenerateJLIClassesPlugin implements Plugin { private static final String NAME = "generate-jli-classes"; - private static final String BMH_PARAM = "bmh"; - private static final String BMH_SPECIES_PARAM = "bmh-species"; - private static final String DESCRIPTION = PluginsResourceBundle.getDescription(NAME); - private static final String DMH_PARAM = "dmh"; private static final String DIRECT_HOLDER = "java/lang/invoke/DirectMethodHandle$Holder"; private static final String DMH_INVOKE_VIRTUAL = "invokeVirtual"; private static final String DMH_INVOKE_STATIC = "invokeStatic"; @@ -61,8 +62,6 @@ public final class GenerateJLIClassesPlugin implements Plugin { private static final String DMH_INVOKE_INTERFACE = "invokeInterface"; private static final String DMH_INVOKE_STATIC_INIT = "invokeStaticInit"; - private static final String INVOKERS_PARAM = "invokers"; - private static final String DELEGATING_HOLDER = "java/lang/invoke/DelegatingMethodHandle$Holder"; private static final String BASIC_FORMS_HOLDER = "java/lang/invoke/LambdaForm$Holder"; private static final String INVOKERS_HOLDER = "java/lang/invoke/Invokers$Holder"; @@ -76,7 +75,6 @@ public final class GenerateJLIClassesPlugin implements Plugin { Map> dmhMethods; - public GenerateJLIClassesPlugin() { } @@ -112,7 +110,7 @@ public final class GenerateJLIClassesPlugin implements Plugin { * A better long-term solution is to define and run a set of quick * generators and extracting this list as a step in the build process. */ - public static List defaultSpecies() { + private static List defaultSpecies() { return List.of("LL", "L3", "L4", "L5", "L6", "L7", "L7I", "L7II", "L7IIL", "L8", "L9", "L10", "L10I", "L10II", "L10IIL", "L11", "L12", "L13", "LI", "D", "L3I", "LIL", "LLI", "LLIL", @@ -122,26 +120,27 @@ public final class GenerateJLIClassesPlugin implements Plugin { /** * @return the default invoker forms to generate. */ - public static List defaultInvokers() { - return List.of("_L", "_I", "I_I", "LI_I", "ILL_I", "LIL_I", "L_L", "LL_V", "LLLL_L"); + private static List defaultInvokers() { + return List.of("LL_L", "LL_I", "LILL_I", "L6_L"); } /** * @return the list of default DirectMethodHandle methods to generate. */ - public static Map> defaultDMHMethods() { + private static Map> defaultDMHMethods() { return Map.of( - DMH_INVOKE_VIRTUAL, List.of("_L", "L_L", "LI_I", "LL_V"), - DMH_INVOKE_SPECIAL, List.of("L_I", "L_L", "LF_L", "LD_L", "LL_L", - "L3_L", "L4_L", "L5_L", "L6_L", "L7_L", "LI_I", "LI_L", "LIL_I", - "LII_I", "LII_L", "LLI_L", "LLI_I", "LILI_I", "LIIL_L", - "LIILL_L", "LIILL_I", "LIIL_I", "LILIL_I", "LILILL_I", - "LILII_I", "LI3_I", "LI3L_I", "LI3LL_I", "LI3_L", "LI4_I"), - DMH_INVOKE_STATIC, List.of("II_I", "IL_I", "ILIL_I", "ILII_I", - "_I", "_L", "_V", "D_L", "F_L", "I_I", "II_L", "LI_L", - "L_V", "L_L", "LL_L", "L3_L", "L4_L", "L5_L", "L6_L", - "L7_L", "L8_L", "L9_L", "L9I_L", "L9II_L", "L9IIL_L", - "L10_L", "L11_L", "L12_L", "L13_L", "L13I_L", "L13II_L") + DMH_INVOKE_VIRTUAL, List.of("L_L", "LL_L", "LLI_I", "L3_V"), + DMH_INVOKE_SPECIAL, List.of("LL_I", "LL_L", "LLF_L", "LLD_L", "L3_L", + "L4_L", "L5_L", "L6_L", "L7_L", "L8_L", "LLI_I", "LLI_L", + "LLIL_I", "LLII_I", "LLII_L", "L3I_L", "L3I_I", "LLILI_I", + "LLIIL_L", "LLIILL_L", "LLIILL_I", "LLIIL_I", "LLILIL_I", + "LLILILL_I", "LLILII_I", "LLI3_I", "LLI3L_I", "LLI3LL_I", + "LLI3_L", "LLI4_I"), + DMH_INVOKE_STATIC, List.of("LII_I", "LIL_I", "LILIL_I", "LILII_I", + "L_I", "L_L", "L_V", "LD_L", "LF_L", "LI_I", "LII_L", "LLI_L", + "LL_V", "LL_L", "L3_L", "L4_L", "L5_L", "L6_L", "L7_L", + "L8_L", "L9_L", "L10_L", "L10I_L", "L10II_L", "L10IIL_L", + "L11_L", "L12_L", "L13_L", "L14_L", "L14I_L", "L14II_L") ); } @@ -160,92 +159,89 @@ public final class GenerateJLIClassesPlugin implements Plugin { public void configure(Map config) { String mainArgument = config.get(NAME); - // Enable by default - boolean bmhEnabled = true; - boolean dmhEnabled = true; - boolean invokersEnabled = true; - if (mainArgument != null) { - List args = Arrays.asList(mainArgument.split(",")); - if (!args.contains(BMH_PARAM)) { - bmhEnabled = false; - } - if (!args.contains(DMH_PARAM)) { - dmhEnabled = false; - } - if (!args.contains(INVOKERS_PARAM)) { - dmhEnabled = false; - } - } + if (mainArgument != null && mainArgument.startsWith("@")) { + File file = new File(mainArgument.substring(1)); + if (file.exists()) { + speciesTypes = new ArrayList<>(); + invokerTypes = new ArrayList<>(); + dmhMethods = new HashMap<>(); + Stream lines = fileLines(file); - if (!bmhEnabled) { - speciesTypes = List.of(); + lines.map(line -> line.split(" ")) + .forEach(parts -> { + switch (parts[0]) { + case "[BMH_RESOLVE]": + speciesTypes.add(expandSignature(parts[1])); + break; + case "[LF_RESOLVE]": + String methodType = parts[3]; + validateMethodType(methodType); + if (parts[1].contains("Invokers")) { + invokerTypes.add(methodType); + } else if (parts[1].contains("DirectMethodHandle")) { + String dmh = parts[2]; + // ignore getObject etc for now (generated + // by default) + if (DMH_METHOD_TYPE_MAP.containsKey(dmh)) { + addDMHMethodType(dmh, methodType); + } + } + break; + default: break; // ignore + } + }); + } } else { - String args = config.get(BMH_SPECIES_PARAM); - List bmhSpecies; - if (args != null && !args.isEmpty()) { - bmhSpecies = Arrays.stream(args.split(",")) - .map(String::trim) - .filter(s -> !s.isEmpty()) - .collect(Collectors.toList()); - } else { - bmhSpecies = defaultSpecies(); - } - + List bmhSpecies = defaultSpecies(); // Expand BMH species signatures speciesTypes = bmhSpecies.stream() .map(type -> expandSignature(type)) .collect(Collectors.toList()); - } - if (!invokersEnabled) { - invokerTypes = List.of(); - } else { - String args = config.get(INVOKERS_PARAM); - if (args != null && !args.isEmpty()) { - invokerTypes = Arrays.stream(args.split(",")) - .map(String::trim) - .filter(s -> !s.isEmpty()) - .collect(Collectors.toList()); - validateMethodTypes(invokerTypes); - } else { - invokerTypes = defaultInvokers(); - } + invokerTypes = defaultInvokers(); + validateMethodTypes(invokerTypes); - } - // DirectMethodHandles - if (!dmhEnabled) { - dmhMethods = Map.of(); - } else { - dmhMethods = new HashMap<>(); - for (String dmhParam : DMH_METHOD_TYPE_MAP.keySet()) { - String args = config.get(dmhParam); - if (args != null && !args.isEmpty()) { - List dmhMethodTypes = Arrays.stream(args.split(",")) - .map(String::trim) - .filter(s -> !s.isEmpty()) - .collect(Collectors.toList()); - dmhMethods.put(dmhParam, dmhMethodTypes); - validateMethodTypes(dmhMethodTypes); - } - } - if (dmhMethods.isEmpty()) { - dmhMethods = defaultDMHMethods(); + dmhMethods = defaultDMHMethods(); + for (List dmhMethodTypes : dmhMethods.values()) { + validateMethodTypes(dmhMethodTypes); } } } - void validateMethodTypes(List dmhMethodTypes) { - for (String type : dmhMethodTypes) { - String[] typeParts = type.split("_"); - // check return type (second part) - if (typeParts.length != 2 || typeParts[1].length() != 1 - || "LJIFDV".indexOf(typeParts[1].charAt(0)) == -1) { - throw new PluginException( - "Method type signature must be of form [LJIFD]*_[LJIFDV]"); - } - // expand and check arguments (first part) - expandSignature(typeParts[0]); + private void addDMHMethodType(String dmh, String methodType) { + validateMethodType(methodType); + List methodTypes = dmhMethods.get(dmh); + if (methodTypes == null) { + methodTypes = new ArrayList<>(); + dmhMethods.put(dmh, methodTypes); } + methodTypes.add(methodType); + } + + private Stream fileLines(File file) { + try { + return Files.lines(file.toPath()); + } catch (IOException io) { + throw new PluginException("Couldn't read file"); + } + } + + private void validateMethodTypes(List dmhMethodTypes) { + for (String type : dmhMethodTypes) { + validateMethodType(type); + } + } + + private void validateMethodType(String type) { + String[] typeParts = type.split("_"); + // check return type (second part) + if (typeParts.length != 2 || typeParts[1].length() != 1 + || "LJIFDV".indexOf(typeParts[1].charAt(0)) == -1) { + throw new PluginException( + "Method type signature must be of form [LJIFD]*_[LJIFDV]"); + } + // expand and check arguments (first part) + expandSignature(typeParts[0]); } private static void requireBasicType(char c) { @@ -304,14 +300,33 @@ public final class GenerateJLIClassesPlugin implements Plugin { for (Map.Entry> entry : dmhMethods.entrySet()) { String dmhType = entry.getKey(); for (String type : entry.getValue()) { - directMethodTypes[index] = asMethodType(type); + // The DMH type to actually ask for is retrieved by removing + // the first argument, which needs to be of Object.class + MethodType mt = asMethodType(type); + if (mt.parameterCount() < 1 || + mt.parameterType(0) != Object.class) { + throw new PluginException( + "DMH type parameter must start with L"); + } + directMethodTypes[index] = mt.dropParameterTypes(0, 1); dmhTypes[index] = DMH_METHOD_TYPE_MAP.get(dmhType); index++; } } MethodType[] invokerMethodTypes = new MethodType[this.invokerTypes.size()]; for (int i = 0; i < invokerTypes.size(); i++) { - invokerMethodTypes[i] = asMethodType(invokerTypes.get(i)); + // The invoker type to ask for is retrieved by removing the first + // and the last argument, which needs to be of Object.class + MethodType mt = asMethodType(invokerTypes.get(i)); + final int lastParam = mt.parameterCount() - 1; + if (mt.parameterCount() < 2 || + mt.parameterType(0) != Object.class || + mt.parameterType(lastParam) != Object.class) { + throw new PluginException( + "Invoker type parameter must start and end with L"); + } + mt = mt.dropParameterTypes(lastParam, lastParam + 1); + invokerMethodTypes[i] = mt.dropParameterTypes(0, 1); } try { byte[] bytes = JLIA.generateDirectMethodHandleHolderClassBytes( diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties index 6fa0248531f..67c40903eb9 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties @@ -68,10 +68,12 @@ exclude-resources.argument= resources to exclude exclude-resources.description=\ Specify resources to exclude. e.g.: **.jcov,glob:**/META-INF/** -generate-jli-classes.argument= +generate-jli-classes.argument=<@filename> generate-jli-classes.description=\ -Concrete java.lang.invoke classes to generate +Takes a file hinting to jlink what java.lang.invoke classes to pre-generate. If\n\ +this flag is not specified a default set of classes will be generated, so to \n\ +disable pre-generation supply the name of an empty or non-existing file installed-modules.description=Fast loading of module descriptors (always enabled) From 616336b6c23d4364c4d30e7095ceae6b56d3886b Mon Sep 17 00:00:00 2001 From: Felix Yang Date: Fri, 26 Aug 2016 08:33:28 -0700 Subject: [PATCH 37/51] 8163561: Add a test for Proxy Authentication in HTTP/2 Client API Reviewed-by: chegar --- .../java/net/httpclient/ProxyAuthTest.java | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 jdk/test/java/net/httpclient/ProxyAuthTest.java diff --git a/jdk/test/java/net/httpclient/ProxyAuthTest.java b/jdk/test/java/net/httpclient/ProxyAuthTest.java new file mode 100644 index 00000000000..42bc0c709db --- /dev/null +++ b/jdk/test/java/net/httpclient/ProxyAuthTest.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ + +/* + * @test + * @bug 8163561 + * @modules java.base/sun.net.www + * @summary Verify that Proxy-Authenticate header is correctly handled + * + * @run main/othervm ProxyAuthTest + */ + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.Authenticator; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.ProxySelector; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpResponse; +import java.util.Base64; + +import sun.net.www.MessageHeader; + +public class ProxyAuthTest { + private static final String AUTH_USER = "user"; + private static final String AUTH_PASSWORD = "password"; + + public static void main(String[] args) throws Exception { + try (ServerSocket ss = new ServerSocket(0)) { + int port = ss.getLocalPort(); + MyProxy proxy = new MyProxy(ss); + (new Thread(proxy)).start(); + System.out.println("Proxy listening port " + port); + + Auth auth = new Auth(); + InetSocketAddress paddr = new InetSocketAddress("localhost", port); + + URI uri = new URI("http://www.google.ie/"); + HttpClient client = HttpClient.create() + .proxy(ProxySelector.of(paddr)) + .authenticator(auth) + .build(); + HttpResponse resp = client.request(uri) + .GET() + .responseAsync() + .get(); + if (resp.statusCode() != 404) { + throw new RuntimeException("Unexpected status code: " + resp.statusCode()); + } + + if (auth.isCalled) { + System.out.println("Authenticator is called"); + } else { + throw new RuntimeException("Authenticator is not called"); + } + + if (!proxy.matched) { + throw new RuntimeException("Proxy authentication failed"); + } + } + } + + static class Auth extends Authenticator { + private volatile boolean isCalled; + + @Override + protected PasswordAuthentication getPasswordAuthentication() { + System.out.println("scheme: " + this.getRequestingScheme()); + isCalled = true; + return new PasswordAuthentication(AUTH_USER, + AUTH_PASSWORD.toCharArray()); + } + } + + static class MyProxy implements Runnable { + final ServerSocket ss; + private volatile boolean matched; + + MyProxy(ServerSocket ss) { + this.ss = ss; + } + + public void run() { + for (int i = 0; i < 2; i++) { + try (Socket s = ss.accept(); + InputStream in = s.getInputStream(); + OutputStream os = s.getOutputStream(); + BufferedWriter writer = new BufferedWriter( + new OutputStreamWriter(os)); + PrintWriter out = new PrintWriter(writer);) { + MessageHeader headers = new MessageHeader(in); + System.out.println("Proxy: received " + headers); + + String authInfo = headers + .findValue("Proxy-Authorization"); + if (authInfo != null) { + authenticate(authInfo); + out.print("HTTP/1.1 404 Not found\r\n"); + out.print("\r\n"); + System.out.println("Proxy: 404"); + out.flush(); + } else { + out.print("HTTP/1.1 407 Proxy Authorization Required\r\n"); + out.print( + "Proxy-Authenticate: Basic realm=\"a fake realm\"\r\n"); + out.print("\r\n"); + System.out.println("Proxy: Authorization required"); + out.flush(); + } + } catch (IOException x) { + System.err.println("Unexpected IOException from proxy."); + x.printStackTrace(); + break; + } + } + } + + private void authenticate(String authInfo) throws IOException { + try { + authInfo.trim(); + int ind = authInfo.indexOf(' '); + String recvdUserPlusPass = authInfo.substring(ind + 1).trim(); + // extract encoded username:passwd + String value = new String( + Base64.getMimeDecoder().decode(recvdUserPlusPass)); + String userPlusPassword = AUTH_USER + ":" + AUTH_PASSWORD; + if (userPlusPassword.equals(value)) { + matched = true; + System.out.println("Proxy: client authentication successful"); + } else { + System.err.println( + "Proxy: client authentication failed, expected [" + + userPlusPassword + "], actual [" + value + + "]"); + } + } catch (Exception e) { + throw new IOException( + "Proxy received invalid Proxy-Authorization value: " + + authInfo); + } + } + } + +} + From e079e3b069be94b3ca3614c292e6ddbde09f62ac Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Fri, 26 Aug 2016 21:31:47 +0530 Subject: [PATCH 38/51] 8164800: Cross targeting Windows Reviewed-by: jlaskey, alanb, mchung --- .../jlink/builder/DefaultImageBuilder.java | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java index 1b37140ed55..6f4c7e59041 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java @@ -78,28 +78,23 @@ public final class DefaultImageBuilder implements ImageBuilder { private final List args; private final Set modules; - public DefaultExecutableImage(Path home, Set modules) { - this(home, modules, createArgs(home)); - } - - private DefaultExecutableImage(Path home, Set modules, - List args) { + DefaultExecutableImage(Path home, Set modules) { Objects.requireNonNull(home); - Objects.requireNonNull(args); if (!Files.exists(home)) { throw new IllegalArgumentException("Invalid image home"); } this.home = home; this.modules = Collections.unmodifiableSet(modules); - this.args = Collections.unmodifiableList(args); + this.args = createArgs(home); } private static List createArgs(Path home) { Objects.requireNonNull(home); List javaArgs = new ArrayList<>(); - javaArgs.add(home.resolve("bin"). - resolve(getJavaProcessName()).toString()); - return javaArgs; + Path binDir = home.resolve("bin"); + String java = Files.exists(binDir.resolve("java"))? "java" : "java.exe"; + javaArgs.add(binDir.resolve(java).toString()); + return Collections.unmodifiableList(javaArgs); } @Override @@ -130,6 +125,7 @@ public final class DefaultImageBuilder implements ImageBuilder { private final Path root; private final Path mdir; private final Set modules = new HashSet<>(); + private String targetOsName; /** * Default image builder constructor. @@ -171,6 +167,10 @@ public final class DefaultImageBuilder implements ImageBuilder { @Override public void storeFiles(ResourcePool files) { try { + // populate release properties up-front. targetOsName + // field is assigned from there and used elsewhere. + Properties release = releaseProperties(files); + files.entries().forEach(f -> { if (!f.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) { try { @@ -186,7 +186,8 @@ public final class DefaultImageBuilder implements ImageBuilder { modules.add(m.name()); } }); - storeFiles(modules, releaseProperties(files)); + + storeFiles(modules, release); if (Files.getFileStore(root).supportsFileAttributeView(PosixFileAttributeView.class)) { // launchers in the bin directory need execute permission @@ -226,6 +227,11 @@ public final class DefaultImageBuilder implements ImageBuilder { props.setProperty("JAVA_VERSION", System.getProperty("java.version")); }); + this.targetOsName = props.getProperty("OS_NAME"); + if (this.targetOsName == null) { + throw new RuntimeException("can't determine target OS from java.base descriptor"); + } + Optional release = pool.findEntry("/java.base/release"); if (release.isPresent()) { try (InputStream is = release.get().content()) { @@ -373,7 +379,7 @@ public final class DefaultImageBuilder implements ImageBuilder { Files.createLink(dstFile, target); } - private static String nativeDir(String filename) { + private String nativeDir(String filename) { if (isWindows()) { if (filename.endsWith(".dll") || filename.endsWith(".diz") || filename.endsWith(".pdb") || filename.endsWith(".map")) { @@ -386,8 +392,8 @@ public final class DefaultImageBuilder implements ImageBuilder { } } - private static boolean isWindows() { - return System.getProperty("os.name").startsWith("Windows"); + private boolean isWindows() { + return targetOsName.startsWith("Windows"); } /** @@ -452,12 +458,10 @@ public final class DefaultImageBuilder implements ImageBuilder { } } - private static String getJavaProcessName() { - return isWindows() ? "java.exe" : "java"; - } - public static ExecutableImage getExecutableImage(Path root) { - if (Files.exists(root.resolve("bin").resolve(getJavaProcessName()))) { + Path binDir = root.resolve("bin"); + if (Files.exists(binDir.resolve("java")) || + Files.exists(binDir.resolve("java.exe"))) { return new DefaultExecutableImage(root, retrieveModules(root)); } return null; From 2d02799b3b3b907cc00b2607c7a5347c5bfb49b9 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Fri, 26 Aug 2016 18:10:12 +0200 Subject: [PATCH 39/51] 8164866: tools/jlink/plugins/GenerateJLIClassesPluginTest.java can't compile after JDK-8163371 Reviewed-by: sundar, vlivanov --- .../plugins/GenerateJLIClassesPlugin.java | 2 +- .../plugins/GenerateJLIClassesPluginTest.java | 41 ------------------- 2 files changed, 1 insertion(+), 42 deletions(-) diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java index 42fe47c97f1..a60a1e934b5 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java @@ -110,7 +110,7 @@ public final class GenerateJLIClassesPlugin implements Plugin { * A better long-term solution is to define and run a set of quick * generators and extracting this list as a step in the build process. */ - private static List defaultSpecies() { + public static List defaultSpecies() { return List.of("LL", "L3", "L4", "L5", "L6", "L7", "L7I", "L7II", "L7IIL", "L8", "L9", "L10", "L10I", "L10II", "L10IIL", "L11", "L12", "L13", "LI", "D", "L3I", "LIL", "LLI", "LLIL", diff --git a/jdk/test/tools/jlink/plugins/GenerateJLIClassesPluginTest.java b/jdk/test/tools/jlink/plugins/GenerateJLIClassesPluginTest.java index 53010cfa217..ae2d3ec5945 100644 --- a/jdk/test/tools/jlink/plugins/GenerateJLIClassesPluginTest.java +++ b/jdk/test/tools/jlink/plugins/GenerateJLIClassesPluginTest.java @@ -73,47 +73,6 @@ public class GenerateJLIClassesPluginTest { classFilesForSpecies(GenerateJLIClassesPlugin.defaultSpecies()), List.of()); - - // Test a valid set of options - result = JImageGenerator.getJLinkTask() - .modulePath(helper.defaultModulePath()) - .output(helper.createNewImageDir("generate-jli")) - .option("--generate-jli-classes=bmh:bmh-species=LL,L3") - .addMods("java.base") - .call(); - - image = result.assertSuccess(); - - JImageValidator.validate( - image.resolve("lib").resolve("modules"), - classFilesForSpecies(List.of("LL", "L3")), - classFilesForSpecies(List.of("L4"))); - - - // Test disabling BMH species generation - result = JImageGenerator.getJLinkTask() - .modulePath(helper.defaultModulePath()) - .output(helper.createNewImageDir("generate-jli")) - .option("--generate-jli-classes=not-bmh:bmh-species=LL,L3") - .addMods("java.base") - .call(); - - image = result.assertSuccess(); - JImageValidator.validate( - image.resolve("lib").resolve("modules"), - List.of(), - classFilesForSpecies(List.of("LL", "L3", "L4"))); - - - // Test an invalid set of options - result = JImageGenerator.getJLinkTask() - .modulePath(helper.defaultModulePath()) - .output(helper.createNewImageDir("generate-jli")) - .option("--generate-jli-classes=bmh:bmh-species=LL,L7V") - .addMods("java.base") - .call(); - - result.assertFailure(); } private static List classFilesForSpecies(List species) { From 0edc4fa72dcf4a1844e14e301c27a75f47e7a798 Mon Sep 17 00:00:00 2001 From: Anthony Scarpino Date: Fri, 26 Aug 2016 09:57:36 -0700 Subject: [PATCH 40/51] 8074838: Resolve disabled warnings for libj2pkcs11 Reviewed-by: wetmore, erikj --- jdk/make/lib/Lib-jdk.crypto.pkcs11.gmk | 4 +--- .../jdk.crypto.pkcs11/share/native/libj2pkcs11/p11_util.c | 2 +- .../unix/native/libj2pkcs11/j2secmod_md.c | 7 ++++--- .../windows/native/libj2pkcs11/j2secmod_md.c | 3 +++ 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/jdk/make/lib/Lib-jdk.crypto.pkcs11.gmk b/jdk/make/lib/Lib-jdk.crypto.pkcs11.gmk index c74f77960bb..82618b11fb5 100644 --- a/jdk/make/lib/Lib-jdk.crypto.pkcs11.gmk +++ b/jdk/make/lib/Lib-jdk.crypto.pkcs11.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -38,8 +38,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJ2PKCS11, \ CFLAGS := $(CFLAGS_JDKLIB) $(addprefix -I, $(LIBJ2PKCS11_SRC)) \ $(LIBJAVA_HEADER_FLAGS) \ -I$(SUPPORT_OUTPUTDIR)/headers/jdk.crypto.pkcs11, \ - DISABLED_WARNINGS_solstudio := E_DECLARATION_IN_CODE, \ - DISABLED_WARNINGS_microsoft := 4013 4267, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libj2pkcs11/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff --git a/jdk/src/jdk.crypto.pkcs11/share/native/libj2pkcs11/p11_util.c b/jdk/src/jdk.crypto.pkcs11/share/native/libj2pkcs11/p11_util.c index f102baa64bf..87d34543731 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/native/libj2pkcs11/p11_util.c +++ b/jdk/src/jdk.crypto.pkcs11/share/native/libj2pkcs11/p11_util.c @@ -558,7 +558,7 @@ void jStringToCKUTF8CharArray(JNIEnv *env, const jstring jArray, CK_UTF8CHAR_PTR pCharArray = (*env)->GetStringUTFChars(env, jArray, &isCopy); if (pCharArray == NULL) { return; } - *ckpLength = strlen(pCharArray); + *ckpLength = (CK_ULONG) strlen(pCharArray); *ckpArray = (CK_UTF8CHAR_PTR) malloc((*ckpLength + 1) * sizeof(CK_UTF8CHAR)); if (*ckpArray == NULL) { (*env)->ReleaseStringUTFChars(env, (jstring) jArray, pCharArray); diff --git a/jdk/src/jdk.crypto.pkcs11/unix/native/libj2pkcs11/j2secmod_md.c b/jdk/src/jdk.crypto.pkcs11/unix/native/libj2pkcs11/j2secmod_md.c index 225263247db..d5154eff606 100644 --- a/jdk/src/jdk.crypto.pkcs11/unix/native/libj2pkcs11/j2secmod_md.c +++ b/jdk/src/jdk.crypto.pkcs11/unix/native/libj2pkcs11/j2secmod_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,6 +49,7 @@ void *findFunction(JNIEnv *env, jlong jHandle, const char *functionName) { JNIEXPORT jlong JNICALL Java_sun_security_pkcs11_Secmod_nssGetLibraryHandle (JNIEnv *env, jclass thisClass, jstring jLibName) { + void *hModule; const char *libName = (*env)->GetStringUTFChars(env, jLibName, NULL); if (libName == NULL) { return 0L; @@ -56,9 +57,9 @@ JNIEXPORT jlong JNICALL Java_sun_security_pkcs11_Secmod_nssGetLibraryHandle // look up existing handle only, do not load #if defined(AIX) - void *hModule = dlopen(libName, RTLD_LAZY); + hModule = dlopen(libName, RTLD_LAZY); #else - void *hModule = dlopen(libName, RTLD_NOLOAD); + hModule = dlopen(libName, RTLD_NOLOAD); #endif dprintf2("-handle for %s: %u\n", libName, hModule); (*env)->ReleaseStringUTFChars(env, jLibName, libName); diff --git a/jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/j2secmod_md.c b/jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/j2secmod_md.c index 33b11bfd07e..6e983ce158f 100644 --- a/jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/j2secmod_md.c +++ b/jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/j2secmod_md.c @@ -31,6 +31,9 @@ #include "j2secmod.h" +extern void throwNullPointerException(JNIEnv *env, const char *message); +extern void throwIOException(JNIEnv *env, const char *message); + void *findFunction(JNIEnv *env, jlong jHandle, const char *functionName) { HINSTANCE hModule = (HINSTANCE)jHandle; void *fAddress = GetProcAddress(hModule, functionName); From f894a28859acab03ac210eb40246752b8ae28be3 Mon Sep 17 00:00:00 2001 From: Svetlana Nikandrova Date: Thu, 25 Aug 2016 20:53:40 +0300 Subject: [PATCH 41/51] 8005068: HttpCookie does not correctly handle negative maxAge values Reviewed-by: chegar --- .../share/classes/java/net/HttpCookie.java | 7 ++- .../net/HttpCookie/CookieNegativeMaxAge.java | 56 +++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 jdk/test/java/net/HttpCookie/CookieNegativeMaxAge.java diff --git a/jdk/src/java.base/share/classes/java/net/HttpCookie.java b/jdk/src/java.base/share/classes/java/net/HttpCookie.java index c8d127837ca..7cc7d6e8ebc 100644 --- a/jdk/src/java.base/share/classes/java/net/HttpCookie.java +++ b/jdk/src/java.base/share/classes/java/net/HttpCookie.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -233,7 +233,7 @@ public final class HttpCookie implements Cloneable { // if not specify max-age, this cookie should be // discarded when user agent is to be closed, but // it is not expired. - if (maxAge == MAX_AGE_UNSPECIFIED) return false; + if (maxAge < 0) return false; long deltaSecond = (System.currentTimeMillis() - whenCreated) / 1000; if (deltaSecond > maxAge) @@ -952,7 +952,8 @@ public final class HttpCookie implements Cloneable { String attrName, String attrValue) { if (cookie.getMaxAge() == MAX_AGE_UNSPECIFIED) { - cookie.setMaxAge(cookie.expiryDate2DeltaSeconds(attrValue)); + long delta = cookie.expiryDate2DeltaSeconds(attrValue); + cookie.setMaxAge(delta > 0 ? delta : 0); } } }); diff --git a/jdk/test/java/net/HttpCookie/CookieNegativeMaxAge.java b/jdk/test/java/net/HttpCookie/CookieNegativeMaxAge.java new file mode 100644 index 00000000000..aae65f4f625 --- /dev/null +++ b/jdk/test/java/net/HttpCookie/CookieNegativeMaxAge.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8005068 + * @summary Check that any negative maxAge is treated as "unspecified" and + * if header contains cookie with "expires" attribute in the past then cookie + * is created with maxAge=0 meaning it is specified to be immediately expired. + * @run main CookieNegativeMaxAge + */ + + +import java.net.HttpCookie; +import java.util.List; + +public class CookieNegativeMaxAge { + + public static void main(String... args) { + HttpCookie cookie = new HttpCookie("testCookie", "value"); + cookie.setMaxAge(Integer.MIN_VALUE); + if (cookie.hasExpired()) { + throw new RuntimeException("Cookie has unexpectedly expired"); + } + + List cookies = HttpCookie.parse("Set-Cookie: " + + "expiredCookie=value; expires=Thu, 01 Jan 1970 00:00:00 GMT"); + if (cookies.size() == 1) { + if (cookies.get(0).getMaxAge() != 0) { + throw new RuntimeException("Cookie maxAge expected to be 0"); + } + } else { + throw new RuntimeException("Header was incorrectly parsed"); + } + } +} From ff0876af590b5be055f94392f7d5e86180f22524 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 25 Aug 2016 21:18:44 +0000 Subject: [PATCH 42/51] Added tag jdk-9+133 for changeset cf75dd18b3cd --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index dd85a0e3b2b..8d8a2e6cf99 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -535,3 +535,4 @@ e96b34b76d863ed1fa04e0eeb3f297ac17b490fd jdk-9+129 7d54c7056328b6a2bf4877458b8f4d8cd870f93b jdk-9+130 943bf73b49c33c2d7cbd796f6a4ae3c7a00ae932 jdk-9+131 713951c08aa26813375175c2ab6cc99ff2a56903 jdk-9+132 +a25e0fb6033245ab075136e744d362ce765464cd jdk-9+133 From 8925d80b0f1e0dca1b9c6d98eae8d3928aea9593 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 25 Aug 2016 21:18:44 +0000 Subject: [PATCH 43/51] Added tag jdk-9+133 for changeset 3d8b2db865d7 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 2ab754ea198..9b00c6661fd 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -375,3 +375,4 @@ f5902d3841b82cac6e7716a20c24e8e916fb14a8 jdk-9+129 d94d54a3192fea79234c3ac55cd0b4052d45e954 jdk-9+130 8728756c2f70a79a90188f4019cfd6b9a275765c jdk-9+131 a24702d4d5ab0015a5c553ed57f66fce7d85155e jdk-9+132 +be1218f792a450dfb5d4b1f82616b9d95a6a732e jdk-9+133 From f4b607169835dff2a1991b023d01cc0fcd369cb7 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 25 Aug 2016 21:18:44 +0000 Subject: [PATCH 44/51] Added tag jdk-9+133 for changeset 93cc31534cc4 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 2ba88ee0421..a959d0d2240 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -375,3 +375,4 @@ c3e83ccab3bb1733ae903d681879a33f85ed465c jdk-9+129 77f9692d5976ae155773dd3e07533616bb95bae1 jdk-9+130 f7e1d5337c2e550fe553df7a3886bbed80292ecd jdk-9+131 1ab4b9399c4cba584f66c1c088188f2f565fbf9c jdk-9+132 +2021bfedf1c478a4808a7711a6090682a12f4c0e jdk-9+133 From 4af40de9e799e96d28bdff96398e2cd882af5893 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 25 Aug 2016 21:18:47 +0000 Subject: [PATCH 45/51] Added tag jdk-9+133 for changeset a3fdd74e324a --- nashorn/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/nashorn/.hgtags b/nashorn/.hgtags index aa139484a6f..f68987a568a 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -366,3 +366,4 @@ ff07be6106fa56b72c163244f45a3ecb4c995564 jdk-9+127 0de67a63e2c73781ecf5979a2f3aa9619a445c37 jdk-9+130 ee77c6b3713ab293e027ac3ea1cc16f86dac535f jdk-9+131 55a75af751dfe44039baef2b762ee7347021025b jdk-9+132 +3a924b820d02b108cf57b51e145b5150d1eedcca jdk-9+133 From 9cda798a33a4ed33709b0c302f5791caa706bfbd Mon Sep 17 00:00:00 2001 From: Bradford Wetmore Date: Fri, 26 Aug 2016 13:44:20 -0700 Subject: [PATCH 46/51] 8061842: Package jurisdiction policy files as something other than JAR Reviewed-by: xuelei, weijun, mullan --- jdk/make/gendata/Gendata-java.base.gmk | 10 +- jdk/make/gendata/GendataCryptoPolicy.gmk | 72 +++++++++ jdk/make/gendata/GendataPolicyJars.gmk | 150 ------------------ .../makejavasecurity/MakeJavaSecurity.java | 22 ++- .../classes/javax/crypto/JceSecurity.java | 138 ++++++++-------- .../share/conf/security/java.security | 50 ++++++ .../share/conf/security/policy/README.txt | 35 ++++ .../policy/limited}/default_US_export.policy | 3 +- .../policy}/limited/default_local.policy | 0 .../policy}/limited/exempt_local.policy | 4 +- .../policy/unlimited/default_US_export.policy | 6 + .../policy}/unlimited/default_local.policy | 1 + .../CryptoPermissions/TestUnlimited.java | 96 +++++++++++ .../JavaDotSecurity/final_java_security | 1 + .../jdk/security/JavaDotSecurity/ifdefs.sh | 10 +- .../JavaDotSecurity/raw_java_security | 1 + 16 files changed, 374 insertions(+), 225 deletions(-) create mode 100644 jdk/make/gendata/GendataCryptoPolicy.gmk delete mode 100644 jdk/make/gendata/GendataPolicyJars.gmk create mode 100644 jdk/src/java.base/share/conf/security/policy/README.txt rename jdk/{make/data/cryptopolicy/unlimited => src/java.base/share/conf/security/policy/limited}/default_US_export.policy (76%) rename jdk/{make/data/cryptopolicy => src/java.base/share/conf/security/policy}/limited/default_local.policy (100%) rename jdk/{make/data/cryptopolicy => src/java.base/share/conf/security/policy}/limited/exempt_local.policy (76%) create mode 100644 jdk/src/java.base/share/conf/security/policy/unlimited/default_US_export.policy rename jdk/{make/data/cryptopolicy => src/java.base/share/conf/security/policy}/unlimited/default_local.policy (99%) create mode 100644 jdk/test/javax/crypto/CryptoPermissions/TestUnlimited.java diff --git a/jdk/make/gendata/Gendata-java.base.gmk b/jdk/make/gendata/Gendata-java.base.gmk index 8547f205011..88acb5b983b 100644 --- a/jdk/make/gendata/Gendata-java.base.gmk +++ b/jdk/make/gendata/Gendata-java.base.gmk @@ -34,7 +34,7 @@ include GendataTZDB.gmk include GendataBlacklistedCerts.gmk -include GendataPolicyJars.gmk +include GendataCryptoPolicy.gmk ################################################################################ @@ -64,13 +64,19 @@ TARGETS += $(GENDATA_CURDATA) GENDATA_JAVA_SECURITY_SRC := $(JDK_TOPDIR)/src/java.base/share/conf/security/java.security GENDATA_JAVA_SECURITY := $(SUPPORT_OUTPUTDIR)/modules_conf/java.base/security/java.security +ifeq ($(UNLIMITED_CRYPTO), true) + CRYPTO.POLICY := unlimited +else + CRYPTO.POLICY := limited +endif + # RESTRICTED_PKGS_SRC is optionally set in custom extension for this makefile $(GENDATA_JAVA_SECURITY): $(BUILD_TOOLS) $(GENDATA_JAVA_SECURITY_SRC) $(RESTRICTED_PKGS_SRC) $(call LogInfo, Generating java.security) $(call MakeDir, $(@D)) $(TOOL_MAKEJAVASECURITY) $(GENDATA_JAVA_SECURITY_SRC) $@ $(OPENJDK_TARGET_OS) \ - $(OPENJDK_TARGET_CPU_ARCH) $(RESTRICTED_PKGS_SRC) + $(OPENJDK_TARGET_CPU_ARCH) $(CRYPTO.POLICY) $(RESTRICTED_PKGS_SRC) TARGETS += $(GENDATA_JAVA_SECURITY) diff --git a/jdk/make/gendata/GendataCryptoPolicy.gmk b/jdk/make/gendata/GendataCryptoPolicy.gmk new file mode 100644 index 00000000000..dff51230b44 --- /dev/null +++ b/jdk/make/gendata/GendataCryptoPolicy.gmk @@ -0,0 +1,72 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# +# In pre-JDK9 releases, Oracle JDK has had a separately downloadable set +# of policy files which has been a nightmare for deployment. +# +# We now create 2 complete initial sets of policy files and package into +# 2 different directories. The crypto.policy Security property will select +# the active policy. +# +# It will be up to the user/deployer to make an informed choice +# as to whether they are legally entitled to use the unlimited policy +# file in their environment. The $(UNLIMITED_CRYPTO) make variable +# determines the default directory/policy. +# + +default: all + +include $(SPEC) +include MakeBase.gmk + + +################################################################################ +POLICY_DIR := $(SUPPORT_OUTPUTDIR)/modules_conf/java.base/security/policy +LIMITED_POLICY_DIR := $(POLICY_DIR)/limited +UNLIMITED_POLICY_DIR := $(POLICY_DIR)/unlimited + +POLICY_SRC_DIR := $(JDK_TOPDIR)/src/java.base/share/conf/security/policy +LIMITED_POLICY_SRC_DIR := $(POLICY_SRC_DIR)/limited +UNLIMITED_POLICY_SRC_DIR := $(POLICY_SRC_DIR)/unlimited + +$(POLICY_DIR)/README.txt: $(POLICY_SRC_DIR)/README.txt + $(install-file) + +$(LIMITED_POLICY_DIR)/%: $(LIMITED_POLICY_SRC_DIR)/% + $(install-file) + +$(UNLIMITED_POLICY_DIR)/%: $(UNLIMITED_POLICY_SRC_DIR)/% + $(install-file) + +TARGETS += \ + $(POLICY_DIR)/README.txt \ + $(LIMITED_POLICY_DIR)/default_US_export.policy \ + $(LIMITED_POLICY_DIR)/default_local.policy \ + $(LIMITED_POLICY_DIR)/exempt_local.policy \ + $(UNLIMITED_POLICY_DIR)/default_US_export.policy \ + $(UNLIMITED_POLICY_DIR)/default_local.policy \ + +################################################################################ diff --git a/jdk/make/gendata/GendataPolicyJars.gmk b/jdk/make/gendata/GendataPolicyJars.gmk deleted file mode 100644 index 57f80abe9f2..00000000000 --- a/jdk/make/gendata/GendataPolicyJars.gmk +++ /dev/null @@ -1,150 +0,0 @@ -# -# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -default: all - -include $(SPEC) -include MakeBase.gmk -include JarArchive.gmk - - -################################################################################ - -US_EXPORT_POLICY_JAR_DST := \ - $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/security/US_export_policy.jar - -US_EXPORT_POLICY_JAR_LIMITED := \ - $(SUPPORT_OUTPUTDIR)/jce/policy/limited/US_export_policy.jar -US_EXPORT_POLICY_JAR_UNLIMITED := \ - $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/US_export_policy.jar - -# -# TODO fix so that SetupJarArchive does not write files into SRCS -# then we don't need this extra copying -# -# NOTE: We currently do not place restrictions on our limited export -# policy. This was not a typo. This means we are shipping the same file -# for both limited and unlimited US_export_policy.jar. Only the local -# policy file currently has restrictions. -# -US_EXPORT_POLICY_JAR_SRC_DIR := \ - $(JDK_TOPDIR)/make/data/cryptopolicy/unlimited -US_EXPORT_POLICY_JAR_TMP := \ - $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/US_export_policy_jar.tmp - -$(US_EXPORT_POLICY_JAR_TMP)/%: $(US_EXPORT_POLICY_JAR_SRC_DIR)/% - $(install-file) - -US_EXPORT_POLICY_JAR_DEPS := \ - $(US_EXPORT_POLICY_JAR_TMP)/default_US_export.policy - -$(eval $(call SetupJarArchive, BUILD_US_EXPORT_POLICY_JAR, \ - DEPENDENCIES := $(US_EXPORT_POLICY_JAR_DEPS), \ - SRCS := $(US_EXPORT_POLICY_JAR_TMP), \ - SUFFIXES := .policy, \ - JAR := $(US_EXPORT_POLICY_JAR_UNLIMITED), \ - EXTRA_MANIFEST_ATTR := Crypto-Strength: unlimited, \ - SKIP_METAINF := true, \ -)) - -$(US_EXPORT_POLICY_JAR_LIMITED): \ - $(US_EXPORT_POLICY_JAR_UNLIMITED) - $(call LogInfo, Copying unlimited $(patsubst $(OUTPUT_ROOT)/%,%,$@)) - $(install-file) - -TARGETS += $(US_EXPORT_POLICY_JAR_LIMITED) $(US_EXPORT_POLICY_JAR_UNLIMITED) - -ifeq ($(UNLIMITED_CRYPTO), true) - $(US_EXPORT_POLICY_JAR_DST): $(US_EXPORT_POLICY_JAR_UNLIMITED) - $(install-file) -else - $(US_EXPORT_POLICY_JAR_DST): $(US_EXPORT_POLICY_JAR_LIMITED) - $(install-file) -endif - -POLICY_JARS += $(US_EXPORT_POLICY_JAR_DST) - -################################################################################ - -LOCAL_POLICY_JAR_DST := \ - $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/security/local_policy.jar - -LOCAL_POLICY_JAR_LIMITED := \ - $(SUPPORT_OUTPUTDIR)/jce/policy/limited/local_policy.jar -LOCAL_POLICY_JAR_UNLIMITED := \ - $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/local_policy.jar - -# -# TODO fix so that SetupJarArchive does not write files into SRCS -# then we don't need this extra copying -# -LOCAL_POLICY_JAR_LIMITED_TMP := \ - $(SUPPORT_OUTPUTDIR)/jce/policy/limited/local_policy_jar.tmp -LOCAL_POLICY_JAR_UNLIMITED_TMP := \ - $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/local_policy_jar.tmp - -$(LOCAL_POLICY_JAR_LIMITED_TMP)/%: \ - $(JDK_TOPDIR)/make/data/cryptopolicy/limited/% - $(install-file) - -$(LOCAL_POLICY_JAR_UNLIMITED_TMP)/%: \ - $(JDK_TOPDIR)/make/data/cryptopolicy/unlimited/% - $(install-file) - -$(eval $(call SetupJarArchive, BUILD_LOCAL_POLICY_JAR_LIMITED, \ - DEPENDENCIES := $(LOCAL_POLICY_JAR_LIMITED_TMP)/exempt_local.policy \ - $(LOCAL_POLICY_JAR_LIMITED_TMP)/default_local.policy, \ - SRCS := $(LOCAL_POLICY_JAR_LIMITED_TMP), \ - SUFFIXES := .policy, \ - JAR := $(LOCAL_POLICY_JAR_LIMITED), \ - EXTRA_MANIFEST_ATTR := Crypto-Strength: limited, \ - SKIP_METAINF := true, \ -)) - -$(eval $(call SetupJarArchive, BUILD_LOCAL_POLICY_JAR_UNLIMITED, \ - DEPENDENCIES := $(LOCAL_POLICY_JAR_UNLIMITED_TMP)/default_local.policy, \ - SRCS := $(LOCAL_POLICY_JAR_UNLIMITED_TMP), \ - SUFFIXES := .policy, \ - JAR := $(LOCAL_POLICY_JAR_UNLIMITED), \ - EXTRA_MANIFEST_ATTR := Crypto-Strength: unlimited, \ - SKIP_METAINF := true, \ -)) - -TARGETS += $(LOCAL_POLICY_JAR_LIMITED) $(LOCAL_POLICY_JAR_UNLIMITED) - -ifeq ($(UNLIMITED_CRYPTO), true) - $(LOCAL_POLICY_JAR_DST): $(LOCAL_POLICY_JAR_UNLIMITED) - $(install-file) -else - $(LOCAL_POLICY_JAR_DST): $(LOCAL_POLICY_JAR_LIMITED) - $(install-file) -endif - -POLICY_JARS += $(LOCAL_POLICY_JAR_DST) -TARGETS += $(POLICY_JARS) - -################################################################################ - -$(eval $(call IncludeCustomExtension, jdk, gendata/GendataPolicyJars.gmk)) diff --git a/jdk/make/src/classes/build/tools/makejavasecurity/MakeJavaSecurity.java b/jdk/make/src/classes/build/tools/makejavasecurity/MakeJavaSecurity.java index 0e3ca50bc26..963db0b593e 100644 --- a/jdk/make/src/classes/build/tools/makejavasecurity/MakeJavaSecurity.java +++ b/jdk/make/src/classes/build/tools/makejavasecurity/MakeJavaSecurity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,8 @@ import java.util.*; * * 1. Adds additional packages to the package.access and * package.definition security properties. - * 2. Filter out platform-unrelated parts + * 2. Filter out platform-unrelated parts. + * 3. Set the JCE jurisdiction policy directory. * * In order to easily maintain platform-related entries, every item * (including the last line) in package.access and package.definition @@ -50,12 +51,13 @@ public class MakeJavaSecurity { public static void main(String[] args) throws Exception { - if (args.length < 4) { + if (args.length < 5) { System.err.println("Usage: java MakeJavaSecurity " + "[input java.security file name] " + "[output java.security file name] " + "[openjdk target os] " + "[openjdk target cpu architecture]" + + "[JCE jurisdiction policy directory]" + "[more restricted packages file name?]"); System.exit(1); @@ -63,8 +65,8 @@ public class MakeJavaSecurity { // more restricted packages List extraLines; - if (args.length == 5) { - extraLines = Files.readAllLines(Paths.get(args[4])); + if (args.length == 6) { + extraLines = Files.readAllLines(Paths.get(args[5])); } else { extraLines = Collections.emptyList(); } @@ -135,6 +137,16 @@ public class MakeJavaSecurity { } } + // Set the JCE policy value + for (int i = 0; i < lines.size(); i++) { + String line = lines.get(i); + int index = line.indexOf("crypto.policydir-tbd"); + if (index >= 0) { + String prefix = line.substring(0, index); + lines.set(i, prefix + args[4]); + } + } + // Clean up the last line of PKG_ACC and PKG_DEF blocks. // Not really necessary since a blank line follows. boolean inBlock = false; diff --git a/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java b/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java index d4fffacf38f..cc32f835696 100644 --- a/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java +++ b/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java @@ -29,6 +29,7 @@ import java.util.*; import java.util.jar.*; import java.io.*; import java.net.URL; +import java.nio.file.*; import java.security.*; import java.security.Provider.Service; @@ -206,7 +207,7 @@ final class JceSecurity { static { try { - NULL_URL = new URL("http://null.sun.com/"); + NULL_URL = new URL("http://null.oracle.com/"); } catch (Exception e) { throw new RuntimeException(e); } @@ -243,83 +244,94 @@ final class JceSecurity { } } + // This is called from within an doPrivileged block. private static void setupJurisdictionPolicies() throws Exception { - String javaHomeDir = System.getProperty("java.home"); - String sep = File.separator; - String pathToPolicyJar = javaHomeDir + sep + "lib" + sep + - "security" + sep; - File exportJar = new File(pathToPolicyJar, "US_export_policy.jar"); - File importJar = new File(pathToPolicyJar, "local_policy.jar"); + // Sanity check the crypto.policy Security property. Single + // directory entry, no pseudo-directories (".", "..", leading/trailing + // path separators). normalize()/getParent() will help later. + String cryptoPolicyProperty = Security.getProperty("crypto.policy"); + Path cpPath = Paths.get(cryptoPolicyProperty); - if (!exportJar.exists() || !importJar.exists()) { - throw new SecurityException - ("Cannot locate policy or framework files!"); + if ((cryptoPolicyProperty == null) || + (cpPath.getNameCount() != 1) || + (cpPath.compareTo(cpPath.getFileName()) != 0)) { + throw new SecurityException( + "Invalid policy directory name format: " + + cryptoPolicyProperty); } - // Read jurisdiction policies. - CryptoPermissions defaultExport = new CryptoPermissions(); - CryptoPermissions exemptExport = new CryptoPermissions(); - loadPolicies(exportJar, defaultExport, exemptExport); + // Prepend java.home to get the full path. normalize() in + // case an extra "." or ".." snuck in somehow. + String javaHomeProperty = System.getProperty("java.home"); + Path javaHomePolicyPath = Paths.get(javaHomeProperty, "conf", + "security", "policy").normalize(); + Path cryptoPolicyPath = Paths.get(javaHomeProperty, "conf", "security", + "policy", cryptoPolicyProperty).normalize(); - CryptoPermissions defaultImport = new CryptoPermissions(); - CryptoPermissions exemptImport = new CryptoPermissions(); - loadPolicies(importJar, defaultImport, exemptImport); - - // Merge the export and import policies for default applications. - if (defaultExport.isEmpty() || defaultImport.isEmpty()) { - throw new SecurityException("Missing mandatory jurisdiction " + - "policy files"); + if (cryptoPolicyPath.getParent().compareTo(javaHomePolicyPath) != 0) { + throw new SecurityException( + "Invalid cryptographic jurisdiction policy directory path: " + + cryptoPolicyProperty); } - defaultPolicy = defaultExport.getMinimum(defaultImport); - // Merge the export and import policies for exempt applications. - if (exemptExport.isEmpty()) { - exemptPolicy = exemptImport.isEmpty() ? null : exemptImport; - } else { - exemptPolicy = exemptExport.getMinimum(exemptImport); + if (!Files.isDirectory(cryptoPolicyPath) + || !Files.isReadable(cryptoPolicyPath)) { + throw new SecurityException( + "Can't read cryptographic policy directory: " + + cryptoPolicyProperty); } - } - /** - * Load the policies from the specified file. Also checks that the - * policies are correctly signed. - */ - private static void loadPolicies(File jarPathName, - CryptoPermissions defaultPolicy, - CryptoPermissions exemptPolicy) - throws Exception { + try (DirectoryStream stream = Files.newDirectoryStream( + cryptoPolicyPath, "{default,exempt}_*.policy")) { + for (Path entry : stream) { + try (InputStream is = new BufferedInputStream( + Files.newInputStream(entry))) { + String filename = entry.getFileName().toString(); - JarFile jf = new JarFile(jarPathName); + CryptoPermissions tmpPerms = new CryptoPermissions(); + tmpPerms.load(is); - Enumeration entries = jf.entries(); - while (entries.hasMoreElements()) { - JarEntry je = entries.nextElement(); - InputStream is = null; - try { - if (je.getName().startsWith("default_")) { - is = jf.getInputStream(je); - defaultPolicy.load(is); - } else if (je.getName().startsWith("exempt_")) { - is = jf.getInputStream(je); - exemptPolicy.load(is); - } else { - continue; - } - } finally { - if (is != null) { - is.close(); + if (filename.startsWith("default_")) { + // Did we find a default perms? + defaultPolicy = ((defaultPolicy == null) ? tmpPerms : + defaultPolicy.getMinimum(tmpPerms)); + } else if (filename.startsWith("exempt_")) { + // Did we find a exempt perms? + exemptPolicy = ((exemptPolicy == null) ? tmpPerms : + exemptPolicy.getMinimum(tmpPerms)); + } else { + // This should never happen. newDirectoryStream + // should only throw return "{default,exempt}_*.policy" + throw new SecurityException( + "Unexpected jurisdiction policy files in : " + + cryptoPolicyProperty); + } + } catch (Exception e) { + throw new SecurityException( + "Couldn't parse jurisdiction policy files in: " + + cryptoPolicyProperty); } } - - // Enforce the signer restraint, i.e. signer of JCE framework - // jar should also be the signer of the two jurisdiction policy - // jar files. - ProviderVerifier.verifyPolicySigned(je.getCertificates()); + } catch (DirectoryIteratorException ex) { + // I/O error encountered during the iteration, + // the cause is an IOException + throw new SecurityException( + "Couldn't iterate through the jurisdiction policy files: " + + cryptoPolicyProperty); + } + + // Must have a default policy + if ((defaultPolicy == null) || defaultPolicy.isEmpty()) { + throw new SecurityException( + "Missing mandatory jurisdiction policy files: " + + cryptoPolicyProperty); + } + + // If there was an empty exempt policy file, ignore it. + if ((exemptPolicy != null) && exemptPolicy.isEmpty()) { + exemptPolicy = null; } - // Close and nullify the JarFile reference to help GC. - jf.close(); - jf = null; } static CryptoPermissions getDefaultPolicy() { diff --git a/jdk/src/java.base/share/conf/security/java.security b/jdk/src/java.base/share/conf/security/java.security index 5154fd05a0f..34e5ac92b47 100644 --- a/jdk/src/java.base/share/conf/security/java.security +++ b/jdk/src/java.base/share/conf/security/java.security @@ -804,6 +804,56 @@ jdk.tls.legacyAlgorithms= \ # EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \ # FFFFFFFF FFFFFFFF, 2} +# Cryptographic Jurisdiction Policy defaults +# +# Due to the import control restrictions of some countries, the default +# JCE policy files allow for strong but "limited" cryptographic key +# lengths to be used. If your country's cryptographic regulations allow, +# the "unlimited" strength policy files can be used instead, which contain +# no restrictions on cryptographic strengths. +# +# If your country has restrictions that don't fit either "limited" or +# "unlimited", an appropriate set of policy files should be created and +# configured before using this distribution. The jurisdiction policy file +# configuration must reflect the cryptographic restrictions appropriate +# for your country. +# +# YOU ARE ADVISED TO CONSULT YOUR EXPORT/IMPORT CONTROL COUNSEL OR ATTORNEY +# TO DETERMINE THE EXACT REQUIREMENTS. +# +# The policy files are flat text files organized into subdirectories of +# /conf/security/policy. Each directory contains a complete +# set of policy files. +# +# The "crypto.policy" Security property controls the directory selection, +# and thus the effective cryptographic policy. +# +# The default set of directories is: +# +# limited | unlimited +# +# however other directories can be created and configured. +# +# Within a directory, the effective policy is the combined minimum +# permissions of the grant statements in the file(s) with the filename +# pattern "default_*.policy". At least one grant is required. For +# example: +# +# limited = Export (all) + Import (limited) = Limited +# unlimited = Export (all) + Import (all) = Unlimited +# +# The effective exemption policy is the combined minimum permissions +# of the grant statements in the file(s) with the filename pattern +# "exempt_*.policy". Exemption grants are optional. +# +# limited = grants exemption permissions, by which the +# effective policy can be circumvented. +# e.g. KeyRecovery/Escrow/Weakening. +# +# Please see the JCA documentation for additional information on these +# files and formats. +crypto.policy=crypto.policydir-tbd + # # The policy for the XML Signature secure validation mode. The mode is # enabled by setting the property "org.jcp.xml.dsig.secureValidation" to diff --git a/jdk/src/java.base/share/conf/security/policy/README.txt b/jdk/src/java.base/share/conf/security/policy/README.txt new file mode 100644 index 00000000000..84e33c972b7 --- /dev/null +++ b/jdk/src/java.base/share/conf/security/policy/README.txt @@ -0,0 +1,35 @@ + + Java(TM) Cryptography Extension Policy Files + for the Java(TM) Platform, Standard Edition Runtime Environment + + README +------------------------------------------------------------------------ + + +The JCE architecture allows flexible cryptographic strength to be +configured via the jurisdiction policy files contained within these +directories. + +Due to import control restrictions of some countries, the default +JCE policy files bundled in this Java Runtime Environment allow +for strong but "limited" cryptographic strengths. For convenience, +this build also contains the "unlimited strength" policy files which +contain no restrictions on cryptographic strengths, but they must be +specifically activated by updating the "crypto.policy" Security property +(e.g. /conf/security/java.security) to point to the appropriate +directory. + +Each subdirectory contains a complete policy configuration, and additional +subdirectories can be added/removed to reflect local regulations. + +JCE for Java SE has been through the U.S. export review process. The JCE +framework, along with the various JCE providers that come standard with it +(SunJCE, SunEC, SunPKCS11, SunMSCAPI, etc), is exportable from the +United States. + +You are advised to consult your export/import control counsel or attorney +to determine the exact requirements of your location, and what policy +settings should be used. + +Please see The Java(TM) Cryptography Architecture (JCA) Reference +Guide and the java.security file for more information. diff --git a/jdk/make/data/cryptopolicy/unlimited/default_US_export.policy b/jdk/src/java.base/share/conf/security/policy/limited/default_US_export.policy similarity index 76% rename from jdk/make/data/cryptopolicy/unlimited/default_US_export.policy rename to jdk/src/java.base/share/conf/security/policy/limited/default_US_export.policy index 67d0acc47a3..1f389340585 100644 --- a/jdk/make/data/cryptopolicy/unlimited/default_US_export.policy +++ b/jdk/src/java.base/share/conf/security/policy/limited/default_US_export.policy @@ -1,4 +1,5 @@ -// Manufacturing policy file. +// Default US Export policy file. + grant { // There is no restriction to any algorithms. permission javax.crypto.CryptoAllPermission; diff --git a/jdk/make/data/cryptopolicy/limited/default_local.policy b/jdk/src/java.base/share/conf/security/policy/limited/default_local.policy similarity index 100% rename from jdk/make/data/cryptopolicy/limited/default_local.policy rename to jdk/src/java.base/share/conf/security/policy/limited/default_local.policy diff --git a/jdk/make/data/cryptopolicy/limited/exempt_local.policy b/jdk/src/java.base/share/conf/security/policy/limited/exempt_local.policy similarity index 76% rename from jdk/make/data/cryptopolicy/limited/exempt_local.policy rename to jdk/src/java.base/share/conf/security/policy/limited/exempt_local.policy index f3255a2d970..9dd5b91b06d 100644 --- a/jdk/make/data/cryptopolicy/limited/exempt_local.policy +++ b/jdk/src/java.base/share/conf/security/policy/limited/exempt_local.policy @@ -1,5 +1,5 @@ -// Some countries have import limits on crypto strength. So this file -// will be useful. +// Some countries have import limits on crypto strength, but may allow for +// these exemptions if the exemption mechanism is used. grant { // There is no restriction to any algorithms if KeyRecovery is enforced. diff --git a/jdk/src/java.base/share/conf/security/policy/unlimited/default_US_export.policy b/jdk/src/java.base/share/conf/security/policy/unlimited/default_US_export.policy new file mode 100644 index 00000000000..1f389340585 --- /dev/null +++ b/jdk/src/java.base/share/conf/security/policy/unlimited/default_US_export.policy @@ -0,0 +1,6 @@ +// Default US Export policy file. + +grant { + // There is no restriction to any algorithms. + permission javax.crypto.CryptoAllPermission; +}; diff --git a/jdk/make/data/cryptopolicy/unlimited/default_local.policy b/jdk/src/java.base/share/conf/security/policy/unlimited/default_local.policy similarity index 99% rename from jdk/make/data/cryptopolicy/unlimited/default_local.policy rename to jdk/src/java.base/share/conf/security/policy/unlimited/default_local.policy index 8dc9702e9da..2b907e25895 100644 --- a/jdk/make/data/cryptopolicy/unlimited/default_local.policy +++ b/jdk/src/java.base/share/conf/security/policy/unlimited/default_local.policy @@ -1,4 +1,5 @@ // Country-specific policy file for countries with no limits on crypto strength. + grant { // There is no restriction to any algorithms. permission javax.crypto.CryptoAllPermission; diff --git a/jdk/test/javax/crypto/CryptoPermissions/TestUnlimited.java b/jdk/test/javax/crypto/CryptoPermissions/TestUnlimited.java new file mode 100644 index 00000000000..e6a8f7f37cc --- /dev/null +++ b/jdk/test/javax/crypto/CryptoPermissions/TestUnlimited.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8061842 + * @summary Package jurisdiction policy files as something other than JAR + * @run main/othervm TestUnlimited "" exception + * @run main/othervm TestUnlimited limited fail + * @run main/othervm TestUnlimited unlimited pass + * @run main/othervm TestUnlimited unlimited/ pass + * @run main/othervm TestUnlimited NosuchDir exception + * @run main/othervm TestUnlimited . exception + * @run main/othervm TestUnlimited /tmp/unlimited exception + * @run main/othervm TestUnlimited ../policy/unlimited exception + * @run main/othervm TestUnlimited ./unlimited exception + * @run main/othervm TestUnlimited /unlimited exception + */ +import javax.crypto.*; +import java.security.Security; + +public class TestUnlimited { + + public static void main(String[] args) throws Exception { + /* + * Override the Security property to allow for unlimited policy. + * Would need appropriate permissions if Security Manager were + * active. + */ + if (args.length != 2) { + throw new Exception("Two args required"); + } + + boolean expected = args[1].equals("pass"); + boolean exception = args[1].equals("exception"); + boolean result = false; + + System.out.println("Testing: " + args[0]); + + if (args[0].equals("\"\"")) { + Security.setProperty("crypto.policy", ""); + } else { + Security.setProperty("crypto.policy", args[0]); + } + + /* + * Use the AES as the test Cipher + * If there is an error initializing, we will never get past here. + */ + try { + int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES"); + System.out.println("max AES key len:" + maxKeyLen); + if (maxKeyLen > 128) { + System.out.println("Unlimited policy is active"); + result = true; + } else { + System.out.println("Unlimited policy is NOT active"); + result = false; + } + } catch (Throwable e) { + if (!exception) { + throw new Exception(); + } + } + + System.out.println( + "Expected:\t" + expected + "\nResult:\t\t" + result); + if (expected != result) { + throw new Exception(); + } + + System.out.println("DONE!"); + } +} diff --git a/jdk/test/jdk/security/JavaDotSecurity/final_java_security b/jdk/test/jdk/security/JavaDotSecurity/final_java_security index cd39bea3560..f5d9c68933c 100644 --- a/jdk/test/jdk/security/JavaDotSecurity/final_java_security +++ b/jdk/test/jdk/security/JavaDotSecurity/final_java_security @@ -10,6 +10,7 @@ foo.5=8 foo.6=9a foo.7=10 foo.8=12 +crypto.policy=somepolicy package.access=sun.,\ solaris.,\ diff --git a/jdk/test/jdk/security/JavaDotSecurity/ifdefs.sh b/jdk/test/jdk/security/JavaDotSecurity/ifdefs.sh index aa1371f71cb..5dc58345fc3 100644 --- a/jdk/test/jdk/security/JavaDotSecurity/ifdefs.sh +++ b/jdk/test/jdk/security/JavaDotSecurity/ifdefs.sh @@ -46,7 +46,13 @@ if [ ! -f $TOOLSRC ]; then fi $JAVAC -d . $TOOLSRC -$JAVA $TOOLNAME $TESTSRC/raw_java_security outfile solaris sparc $TESTSRC/more_restricted +$JAVA $TOOLNAME \ + $TESTSRC/raw_java_security \ + outfile \ + solaris \ + sparc \ + somepolicy \ + $TESTSRC/more_restricted # On Windows, line end could be different. -b is a cross-platform option. -diff -b outfile $TESTSRC/final_java_security \ No newline at end of file +diff -b outfile $TESTSRC/final_java_security diff --git a/jdk/test/jdk/security/JavaDotSecurity/raw_java_security b/jdk/test/jdk/security/JavaDotSecurity/raw_java_security index 8a8a7d3cdde..9aa3c42e668 100644 --- a/jdk/test/jdk/security/JavaDotSecurity/raw_java_security +++ b/jdk/test/jdk/security/JavaDotSecurity/raw_java_security @@ -44,6 +44,7 @@ foo.tbd=11 #ifndef macosx-x64 foo.tbd=12 #endif +crypto.policy=crypto.policydir-tbd package.access=sun.,\ #ifdef solaris From ea29d586dd3ed3bd2ca62eeb0cddf88f19f4ea6c Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Mon, 29 Aug 2016 11:23:34 +0200 Subject: [PATCH 47/51] 8164649: Cleanup of test java/nio/channels/FileChannel/Lock.java Reviewed-by: alanb --- .../java/nio/channels/FileChannel/Lock.java | 252 +++++++++--------- 1 file changed, 129 insertions(+), 123 deletions(-) diff --git a/jdk/test/java/nio/channels/FileChannel/Lock.java b/jdk/test/java/nio/channels/FileChannel/Lock.java index 87f470835e7..8dee478ea82 100644 --- a/jdk/test/java/nio/channels/FileChannel/Lock.java +++ b/jdk/test/java/nio/channels/FileChannel/Lock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,8 +22,8 @@ */ /* @test - * @bug 4429043 4493595 6332756 6709457 - * @summary The FileChannel file locking + * @bug 4429043 4493595 6332756 6709457 7146506 + * @summary Test FileChannel file locking */ import java.io.*; @@ -33,17 +33,14 @@ import static java.nio.file.StandardOpenOption.*; /** * Testing FileChannel's lock method. */ - public class Lock { public static void main(String[] args) throws Exception { - if (args.length > 0) { - if(args[0].equals("1")) { - MadWriter mw = new MadWriter(args[1], false); - } else { - MadWriter mw = new MadWriter(args[1], true); - } + if (args.length == 2) { + attemptLock(args[1], args[0].equals("2")); return; + } else if (args.length != 0) { + throw new RuntimeException("Wrong number of parameters."); } File blah = File.createTempFile("blah", null); blah.deleteOnExit(); @@ -56,120 +53,128 @@ public class Lock { test2(blah, false); test3(blah); test4(blah); - blah.delete(); - } - - private static void test2(File blah, boolean b) throws Exception { - RandomAccessFile raf = new RandomAccessFile(blah, "rw"); - FileChannel channel = raf.getChannel(); - FileLock lock; - if (b) - lock = channel.lock(); - else - lock = channel.tryLock(); - lock.release(); - channel.close(); } + /** + * Test mutual locking with other process + */ static void test1(File blah, String str) throws Exception { + try (RandomAccessFile fis = new RandomAccessFile(blah, "rw")) { + FileChannel fc = fis.getChannel(); + FileLock lock = null; - // Grab the lock - RandomAccessFile fis = new RandomAccessFile(blah, "rw"); - FileChannel fc = fis.getChannel(); - FileLock lock = null; - - if (str.equals("1")) { - lock = fc.lock(0, 10, false); - if (lock == null) - throw new RuntimeException("Lock should not return null"); - try { - FileLock lock2 = fc.lock(5, 10, false); - throw new RuntimeException("Overlapping locks allowed"); - } catch (OverlappingFileLockException e) { - // Correct result + // grab the lock + if (str.equals("1")) { + lock = fc.lock(0, 10, false); + if (lock == null) + throw new RuntimeException("Lock should not return null"); + try { + fc.lock(5, 10, false); + throw new RuntimeException("Overlapping locks allowed"); + } catch (OverlappingFileLockException e) {} // correct result } - } - // Exec the tamperer - String command = System.getProperty("java.home") + - File.separator + "bin" + File.separator + "java"; - String testClasses = System.getProperty("test.classes"); - if (testClasses != null) - command += " -cp " + testClasses; - command += " Lock " + str + " " + blah; - Process p = Runtime.getRuntime().exec(command); + // execute the tamperer + String command = System.getProperty("java.home") + + File.separator + "bin" + File.separator + "java"; + String testClasses = System.getProperty("test.classes"); + if (testClasses != null) + command += " -cp " + testClasses; + command += " Lock " + str + " " + blah; + Process p = Runtime.getRuntime().exec(command); - BufferedReader in = new BufferedReader - (new InputStreamReader(p.getInputStream())); - - String s; - int count = 0; - while ((s = in.readLine()) != null) { - if (!s.equals("good")) { - if (File.separatorChar == '/') { - // Fails on windows over NFS... - throw new RuntimeException("Failed: "+s); + // evaluate System.out of child process + String s; + boolean hasOutput = false; + InputStreamReader isr; + isr = new InputStreamReader(p.getInputStream()); + BufferedReader br = new BufferedReader(isr); + while ((s = br.readLine()) != null) { + // only throw on Unix as windows over NFS fails... + if ((File.separatorChar == '/') && !s.equals("good")) { + throw new RuntimeException("Failed: " + s); } + hasOutput = true; } - count++; - } - if (count == 0) { - in = new BufferedReader(new InputStreamReader(p.getErrorStream())); - while ((s = in.readLine()) != null) { - System.err.println("Error output: " + s); + // evaluate System.err in case of System.out of child process + // was empty + if (!hasOutput) { + isr = new InputStreamReader(p.getErrorStream()); + br = new BufferedReader(isr); + if ((s = br.readLine()) != null) { + System.err.println("Error output:"); + System.err.println(s); + while ((s = br.readLine()) != null) { + System.err.println(s); + } + } + throw new RuntimeException("Failed, no output"); } - throw new RuntimeException("Failed, no output"); - } - // Clean up - if (lock != null) { - /* Check multiple releases */ - lock.release(); - lock.release(); + // clean up, check multiple releases + if (lock != null) { + lock.release(); + lock.release(); + } } - fc.close(); - fis.close(); } - // The overlap check for file locks should be JVM-wide - private static void test3(File blah) throws Exception { - FileChannel fc1 = new RandomAccessFile(blah, "rw").getChannel(); - FileChannel fc2 = new RandomAccessFile(blah, "rw").getChannel(); - - // lock via one channel, and then attempt to lock the same file - // using a second channel - FileLock fl1 = fc1.lock(); - try { - fc2.tryLock(); - throw new RuntimeException("Overlapping locks allowed"); - } catch (OverlappingFileLockException x) { + /** + * Basic test for FileChannel.lock() and FileChannel.tryLock() + */ + static void test2(File blah, boolean b) throws Exception { + try (RandomAccessFile raf = new RandomAccessFile(blah, "rw")) { + FileChannel channel = raf.getChannel(); + FileLock lock; + if (b) + lock = channel.lock(); + else + lock = channel.tryLock(); + lock.release(); } - try { + } + + /** + * Test that overlapping file locking is not possible when using different + * FileChannel objects to the same file path + */ + static void test3(File blah) throws Exception { + try (RandomAccessFile raf1 = new RandomAccessFile(blah, "rw"); + RandomAccessFile raf2 = new RandomAccessFile(blah, "rw")) + { + FileChannel fc1 = raf1.getChannel(); + FileChannel fc2 = raf2.getChannel(); + + // lock via one channel, and then attempt to lock the same file + // using a second channel + FileLock fl1 = fc1.lock(); + try { + fc2.tryLock(); + throw new RuntimeException("Overlapping locks allowed"); + } catch (OverlappingFileLockException x) {} + try { + fc2.lock(); + throw new RuntimeException("Overlapping locks allowed"); + } catch (OverlappingFileLockException x) {} + + // release lock and the attempt to lock with the second channel + // should succeed. + fl1.release(); fc2.lock(); - throw new RuntimeException("Overlapping locks allowed"); - } catch (OverlappingFileLockException x) { + try { + fc1.lock(); + throw new RuntimeException("Overlapping locks allowed"); + } catch (OverlappingFileLockException x) {} } - - // release lock and the attempt to lock with the second channel - // should succeed. - fl1.release(); - FileLock fl2 = fc2.lock(); - try { - fc1.lock(); - throw new RuntimeException("Overlapping locks allowed"); - } catch (OverlappingFileLockException x) { - } - - fc1.close(); - fc2.close(); } /** * Test file locking when file is opened for append */ static void test4(File blah) throws Exception { - try (FileChannel fc = new FileOutputStream(blah, true).getChannel()) { + try (FileOutputStream fos = new FileOutputStream(blah, true)) { + FileChannel fc = fos.getChannel(); fc.tryLock().release(); fc.tryLock(0L, 1L, false).release(); fc.lock().release(); @@ -182,30 +187,31 @@ public class Lock { fc.lock(0L, 1L, false).release(); } } -} -class MadWriter { - public MadWriter(String s, boolean b) throws Exception { - File f = new File(s); - RandomAccessFile fos = new RandomAccessFile(f, "rw"); - FileChannel fc = fos.getChannel(); - if (fc.tryLock(10, 10, false) == null) { - System.out.println("bad: Failed to grab adjacent lock"); + /** + * Utility method to be run in secondary process which tries to acquire a + * lock on a FileChannel + */ + static void attemptLock(String fileName, + boolean expectsLock) throws Exception + { + File f = new File(fileName); + try (RandomAccessFile raf = new RandomAccessFile(f, "rw")) { + FileChannel fc = raf.getChannel(); + if (fc.tryLock(10, 10, false) == null) { + System.out.println("bad: Failed to grab adjacent lock"); + } + if (fc.tryLock(0, 10, false) == null) { + if (expectsLock) + System.out.println("bad"); + else + System.out.println("good"); + } else { + if (expectsLock) + System.out.println("good"); + else + System.out.println("bad"); + } } - FileLock lock = fc.tryLock(0, 10, false); - if (lock == null) { - if (b) - System.out.println("bad"); - else - System.out.println("good"); - } else { - if (b) - System.out.println("good"); - else - System.out.println("bad"); - } - fc.close(); - fos.close(); } - } From 1bc574a5347b6e729dfdc093c9c439ec2594a121 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 29 Aug 2016 09:10:07 -0300 Subject: [PATCH 48/51] 8161000: GPL header incorrect - classfile/classpath Reviewed-by: sundar --- .../classes/jdk/tools/jlink/internal/PathResourcePoolEntry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathResourcePoolEntry.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathResourcePoolEntry.java index 7b7cba3575e..e7c0c87a5ff 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathResourcePoolEntry.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathResourcePoolEntry.java @@ -5,7 +5,7 @@ * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classfile" exception as provided + * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT From 10cbe0678ac9e09a5902e1126d5d75e33d4d9986 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Mon, 29 Aug 2016 21:09:36 +0530 Subject: [PATCH 49/51] 8159004: jlink attempts to create launcher scripts when root/bin dir does not exist Reviewed-by: jlaskey, alanb --- .../tools/jlink/builder/DefaultImageBuilder.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java index 6f4c7e59041..aaccb4269a0 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java @@ -90,11 +90,9 @@ public final class DefaultImageBuilder implements ImageBuilder { private static List createArgs(Path home) { Objects.requireNonNull(home); - List javaArgs = new ArrayList<>(); Path binDir = home.resolve("bin"); String java = Files.exists(binDir.resolve("java"))? "java" : "java.exe"; - javaArgs.add(binDir.resolve(java).toString()); - return Collections.unmodifiableList(javaArgs); + return List.of(binDir.resolve(java).toString()); } @Override @@ -170,6 +168,7 @@ public final class DefaultImageBuilder implements ImageBuilder { // populate release properties up-front. targetOsName // field is assigned from there and used elsewhere. Properties release = releaseProperties(files); + Path bin = root.resolve("bin"); files.entries().forEach(f -> { if (!f.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) { @@ -191,7 +190,6 @@ public final class DefaultImageBuilder implements ImageBuilder { if (Files.getFileStore(root).supportsFileAttributeView(PosixFileAttributeView.class)) { // launchers in the bin directory need execute permission - Path bin = root.resolve("bin"); if (Files.isDirectory(bin)) { Files.list(bin) .filter(f -> !f.toString().endsWith(".diz")) @@ -209,7 +207,11 @@ public final class DefaultImageBuilder implements ImageBuilder { } } - prepareApplicationFiles(files, modules); + // If native files are stripped completely, /bin dir won't exist! + // So, don't bother generating launcher scripts. + if (Files.isDirectory(bin)) { + prepareApplicationFiles(files, modules); + } } catch (IOException ex) { throw new PluginException(ex); } @@ -229,7 +231,7 @@ public final class DefaultImageBuilder implements ImageBuilder { this.targetOsName = props.getProperty("OS_NAME"); if (this.targetOsName == null) { - throw new RuntimeException("can't determine target OS from java.base descriptor"); + throw new PluginException("TargetPlatform attribute is missing for java.base module"); } Optional release = pool.findEntry("/java.base/release"); From af8dc755fd32acba874bc2d2204393d0a071ae48 Mon Sep 17 00:00:00 2001 From: Svetlana Nikandrova Date: Mon, 29 Aug 2016 20:55:06 +0300 Subject: [PATCH 50/51] 8164533: sun/security/ssl/SSLSocketImpl/CloseSocket.java failed with "Error while cleaning up threads after test" Reviewed-by: xuelei --- .../ssl/SSLSocketImpl/CloseSocket.java | 135 +++++++++++------- 1 file changed, 82 insertions(+), 53 deletions(-) diff --git a/jdk/test/sun/security/ssl/SSLSocketImpl/CloseSocket.java b/jdk/test/sun/security/ssl/SSLSocketImpl/CloseSocket.java index 4c532beb8ac..12bfb4ef001 100644 --- a/jdk/test/sun/security/ssl/SSLSocketImpl/CloseSocket.java +++ b/jdk/test/sun/security/ssl/SSLSocketImpl/CloseSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,67 +26,96 @@ * @bug 4674913 * @summary Verify that EOFException are correctly handled during the handshake * @author Andreas Sterbenz + * @run main/othervm CloseSocket */ -import java.io.*; -import java.net.*; - -import javax.net.ssl.*; +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; public class CloseSocket { - public static void main(String[] args) throws Exception { - final ServerSocket serverSocket = new ServerSocket(0); - int serverPort = serverSocket.getLocalPort(); - new Thread() { - public void run() { - try { - Socket s = serverSocket.accept(); - System.out.println("Server accepted connection"); - // wait a bit before closing the socket to give - // the client time to send its hello message - Thread.currentThread().sleep(100); - s.close(); - System.out.println("Server closed socket, done."); - } catch (Exception e) { - System.out.println("Server exception:"); - e.printStackTrace(); - } - } - }.start(); - SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault(); - SSLSocket socket = (SSLSocket)factory.createSocket("localhost", serverPort); - System.out.println("Client established TCP connection"); - boolean failed = false; - try { - System.out.println("Starting handshake..."); - socket.startHandshake(); - System.out.println("ERROR: no exception"); - failed = true; - } catch (IOException e) { - System.out.println("Failed as expected: " + e); - } - try { - System.out.println("Trying read..."); + private static ArrayList testCases = new ArrayList<>(); + + static { + testCases.add(socket -> socket.startHandshake()); + testCases.add(socket -> { InputStream in = socket.getInputStream(); - int b = in.read(); - System.out.println("ERROR: no exception, read: " + b); - failed = true; - } catch (IOException e) { - System.out.println("Failed as expected: " + e); - } - try { - System.out.println("Trying read..."); + in.read(); + }); + testCases.add(socket -> { OutputStream out = socket.getOutputStream(); out.write(43); - System.out.println("ERROR: no exception"); - failed = true; - } catch (IOException e) { - System.out.println("Failed as expected: " + e); - } - if (failed) { - throw new Exception("One or more tests failed"); + }); + } + + public static void main(String[] args) throws Exception { + try (Server server = new Server()) { + new Thread(server).start(); + + SocketFactory factory = SSLSocketFactory.getDefault(); + try (SSLSocket socket = (SSLSocket) factory.createSocket("localhost", + server.getPort())) { + socket.setSoTimeout(2000); + System.out.println("Client established TCP connection"); + boolean failed = false; + for (TestCase testCase : testCases) { + try { + testCase.test(socket); + System.out.println("ERROR: no exception"); + failed = true; + } catch (IOException e) { + System.out.println("Failed as expected: " + e); + } + } + if (failed) { + throw new Exception("One or more tests failed"); + } + } } } + static class Server implements AutoCloseable, Runnable { + + final ServerSocket serverSocket; + + Server() throws IOException { + serverSocket = new ServerSocket(0); + } + + public int getPort() { + return serverSocket.getLocalPort(); + } + + @Override + public void run() { + try (Socket s = serverSocket.accept()) { + System.out.println("Server accepted connection"); + // wait a bit before closing the socket to give + // the client time to send its hello message + Thread.currentThread().sleep(100); + s.close(); + System.out.println("Server closed socket, done."); + } catch (Exception e) { + throw new RuntimeException("Problem in test execution", e); + } + } + + @Override + public void close() throws Exception { + if (!serverSocket.isClosed()) { + serverSocket.close(); + } + } + } + + interface TestCase { + void test(SSLSocket socket) throws IOException; + } } From bc903b0547261120546a1ee9ec71d386fb74c8d2 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Mon, 29 Aug 2016 11:39:12 -0700 Subject: [PATCH 51/51] 8066577: Cleanup and make better use of the stream API in the jrtfs code Reviewed-by: alanb, psandoz, redestad --- .../internal/jrtfs/JrtDirectoryStream.java | 30 +++++++++---------- .../jdk/internal/jrtfs/JrtFileSystem.java | 8 ++--- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtDirectoryStream.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtDirectoryStream.java index eced854d9d8..f2f2aa684c3 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtDirectoryStream.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtDirectoryStream.java @@ -47,8 +47,8 @@ final class JrtDirectoryStream implements DirectoryStream { private final JrtPath dir; private final DirectoryStream.Filter filter; - private volatile boolean isClosed; - private volatile Iterator itr; + private boolean isClosed; + private Iterator itr; JrtDirectoryStream(JrtPath dir, DirectoryStream.Filter filter) @@ -73,24 +73,22 @@ final class JrtDirectoryStream implements DirectoryStream { throw new IllegalStateException(e); } return new Iterator() { - private Path next; @Override - public synchronized boolean hasNext() { - if (isClosed) - return false; - return itr.hasNext(); + public boolean hasNext() { + synchronized (JrtDirectoryStream.this) { + if (isClosed) + return false; + return itr.hasNext(); + } } @Override - public synchronized Path next() { - if (isClosed) - throw new NoSuchElementException(); - return itr.next(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); + public Path next() { + synchronized (JrtDirectoryStream.this) { + if (isClosed) + throw new NoSuchElementException(); + return itr.next(); + } } }; } diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java index 5f0433b9d3b..cb6c85d11e3 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java @@ -119,9 +119,7 @@ class JrtFileSystem extends FileSystem { @Override public Iterable getRootDirectories() { - ArrayList dirs = new ArrayList<>(); - dirs.add(getRootPath()); - return dirs; + return Collections.singleton(getRootPath()); } @Override @@ -159,9 +157,7 @@ class JrtFileSystem extends FileSystem { @Override public final Iterable getFileStores() { - ArrayList list = new ArrayList<>(1); - list.add(getFileStore(getRootPath())); - return list; + return Collections.singleton(getFileStore(getRootPath())); } private static final Set supportedFileAttributeViews