--- a/jdk/make/gensrc/GensrcLocaleData.gmk Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/make/gensrc/GensrcLocaleData.gmk Thu Dec 22 18:48:53 2016 +0000
@@ -64,7 +64,7 @@
BASE_LOCALES := en en-US
# Locales that don't have any resource files should be included here.
-ALL_NON_BASE_LOCALES := ja-JP-JP nb-NO nn-NO th-TH-TH
+ALL_NON_BASE_LOCALES := ja-JP-JP th-TH-TH
SED_BASEARGS := -e 's|$(HASH)warn This file is preprocessed before being compiled|// -- This file was mechanically generated: Do not edit! -- //|g'
SED_NONBASEARGS := $(SED_BASEARGS)
@@ -89,6 +89,10 @@
$1_NON_BASE_LOCALES := $$(subst zh-MO,zh-MO$$(SPACE)zh-Hant-MO, $$($1_NON_BASE_LOCALES))
$1_NON_BASE_LOCALES := $$(subst zh-TW,zh-TW$$(SPACE)zh-Hant-TW, $$($1_NON_BASE_LOCALES))
+# Adding implict locales nn-NO and nb-NO
+ $1_NON_BASE_LOCALES += nn-NO nb-NO
+ $1_NON_BASE_LOCALES := $$(sort $$($1_NON_BASE_LOCALES))
+
ALL_BASE_LOCALES += $$($1_BASE_LOCALES)
ALL_NON_BASE_LOCALES += $$($1_NON_BASE_LOCALES)
--- a/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java Thu Dec 22 18:48:53 2016 +0000
@@ -487,10 +487,43 @@
metaInfo.get("AvailableLocales").add(toLanguageTag(bundle.getID()));
addLikelySubtags(metaInfo, "AvailableLocales", bundle.getID());
}
-
+ addCldrImplicitLocales(metaInfo);
bundleGenerator.generateMetaInfo(metaInfo);
}
+ /**
+ * These are the Locales that are implicitly supported by CLDR.
+ * Adding them explicitly as likelySubtags here, will ensure that
+ * COMPAT locales do not precede them during ResourceBundle search path.
+ */
+ private static void addCldrImplicitLocales(Map<String, SortedSet<String>> metaInfo) {
+ metaInfo.get("LocaleNames").add("zh-Hans-CN");
+ metaInfo.get("LocaleNames").add("zh-Hans-SG");
+ metaInfo.get("LocaleNames").add("zh-Hant-HK");
+ metaInfo.get("LocaleNames").add("zh-Hant-MO");
+ metaInfo.get("LocaleNames").add("zh-Hant-TW");
+ metaInfo.get("CurrencyNames").add("zh-Hans-CN");
+ metaInfo.get("CurrencyNames").add("zh-Hans-SG");
+ metaInfo.get("CurrencyNames").add("zh-Hant-HK");
+ metaInfo.get("CurrencyNames").add("zh-Hant-MO");
+ metaInfo.get("CurrencyNames").add("zh-Hant-TW");
+ metaInfo.get("TimeZoneNames").add("zh-Hans-CN");
+ metaInfo.get("TimeZoneNames").add("zh-Hans-SG");
+ metaInfo.get("TimeZoneNames").add("zh-Hant-HK");
+ metaInfo.get("TimeZoneNames").add("zh-Hant-MO");
+ metaInfo.get("TimeZoneNames").add("zh-Hant-TW");
+ metaInfo.get("TimeZoneNames").add("zh-HK");
+ metaInfo.get("CalendarData").add("zh-Hans-CN");
+ metaInfo.get("CalendarData").add("zh-Hans-SG");
+ metaInfo.get("CalendarData").add("zh-Hant-HK");
+ metaInfo.get("CalendarData").add("zh-Hant-MO");
+ metaInfo.get("CalendarData").add("zh-Hant-TW");
+ metaInfo.get("FormatData").add("zh-Hans-CN");
+ metaInfo.get("FormatData").add("zh-Hans-SG");
+ metaInfo.get("FormatData").add("zh-Hant-HK");
+ metaInfo.get("FormatData").add("zh-Hant-MO");
+ metaInfo.get("FormatData").add("zh-Hant-TW");
+ }
static final Map<String, String> aliases = new HashMap<>();
/**
--- a/jdk/src/java.base/share/classes/java/nio/file/FileTreeWalker.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/nio/file/FileTreeWalker.java Thu Dec 22 18:48:53 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2013, 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
@@ -353,12 +353,13 @@
}
}
- // no next entry so close and pop directory, creating corresponding event
+ // no next entry so close and pop directory,
+ // creating corresponding event
if (entry == null) {
try {
top.stream().close();
} catch (IOException e) {
- if (ioe != null) {
+ if (ioe == null) {
ioe = e;
} else {
ioe.addSuppressed(e);
--- a/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java Thu Dec 22 18:48:53 2016 +0000
@@ -758,16 +758,6 @@
dfs = y;
}
}
- // If the bundle's locale isn't the target locale, put another cache
- // entry for the bundle's locale.
- Locale bundleLocale = resource.getLocale();
- if (!bundleLocale.equals(locale)) {
- SoftReference<DateFormatSymbols> z
- = cachedInstances.putIfAbsent(bundleLocale, ref);
- if (z != null && z.get() == null) {
- cachedInstances.replace(bundleLocale, z, ref);
- }
- }
}
// Copy the field values from dfs to this instance.
--- a/jdk/src/java.base/share/classes/java/time/LocalDateTime.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/LocalDateTime.java Thu Dec 22 18:48:53 2016 +0000
@@ -1407,8 +1407,8 @@
* </ol>
* <p>
* For example, 2008-02-29 (leap year) minus one year would result in the
- * invalid date 2009-02-29 (standard year). Instead of returning an invalid
- * result, the last valid day of the month, 2009-02-28, is selected instead.
+ * invalid date 2007-02-29 (standard year). Instead of returning an invalid
+ * result, the last valid day of the month, 2007-02-28, is selected instead.
* <p>
* This instance is immutable and unaffected by this method call.
*
@@ -1431,8 +1431,8 @@
* </ol>
* <p>
* For example, 2007-03-31 minus one month would result in the invalid date
- * 2007-04-31. Instead of returning an invalid result, the last valid day
- * of the month, 2007-04-30, is selected instead.
+ * 2007-02-31. Instead of returning an invalid result, the last valid day
+ * of the month, 2007-02-28, is selected instead.
* <p>
* This instance is immutable and unaffected by this method call.
*
--- a/jdk/src/java.base/share/classes/java/time/OffsetDateTime.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/OffsetDateTime.java Thu Dec 22 18:48:53 2016 +0000
@@ -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
@@ -1393,8 +1393,8 @@
* </ol>
* <p>
* For example, 2008-02-29 (leap year) minus one year would result in the
- * invalid date 2009-02-29 (standard year). Instead of returning an invalid
- * result, the last valid day of the month, 2009-02-28, is selected instead.
+ * invalid date 2007-02-29 (standard year). Instead of returning an invalid
+ * result, the last valid day of the month, 2007-02-28, is selected instead.
* <p>
* This instance is immutable and unaffected by this method call.
*
@@ -1417,8 +1417,8 @@
* </ol>
* <p>
* For example, 2007-03-31 minus one month would result in the invalid date
- * 2007-04-31. Instead of returning an invalid result, the last valid day
- * of the month, 2007-04-30, is selected instead.
+ * 2007-02-31. Instead of returning an invalid result, the last valid day
+ * of the month, 2007-02-28, is selected instead.
* <p>
* This instance is immutable and unaffected by this method call.
*
@@ -1437,7 +1437,7 @@
* the month and year fields as necessary to ensure the result remains valid.
* The result is only invalid if the maximum/minimum year is exceeded.
* <p>
- * For example, 2008-12-31 minus one week would result in 2009-01-07.
+ * For example, 2009-01-07 minus one week would result in 2008-12-31.
* <p>
* This instance is immutable and unaffected by this method call.
*
@@ -1456,7 +1456,7 @@
* month and year fields as necessary to ensure the result remains valid.
* The result is only invalid if the maximum/minimum year is exceeded.
* <p>
- * For example, 2008-12-31 minus one day would result in 2009-01-01.
+ * For example, 2009-01-01 minus one day would result in 2008-12-31.
* <p>
* This instance is immutable and unaffected by this method call.
*
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java Thu Dec 22 18:48:53 2016 +0000
@@ -1774,16 +1774,20 @@
if (count > 1) {
throw new IllegalArgumentException("Too many pattern letters: " + cur);
}
- appendInternal(new WeekBasedFieldPrinterParser(cur, count));
+ appendValue(new WeekBasedFieldPrinterParser(cur, count, count, count));
} else if (cur == 'w') {
// Fields defined by Locale
if (count > 2) {
throw new IllegalArgumentException("Too many pattern letters: " + cur);
}
- appendInternal(new WeekBasedFieldPrinterParser(cur, count));
+ appendValue(new WeekBasedFieldPrinterParser(cur, count, count, 2));
} else if (cur == 'Y') {
// Fields defined by Locale
- appendInternal(new WeekBasedFieldPrinterParser(cur, count));
+ if (count == 2) {
+ appendValue(new WeekBasedFieldPrinterParser(cur, count, count, 2));
+ } else {
+ appendValue(new WeekBasedFieldPrinterParser(cur, count, count, 19));
+ }
} else {
throw new IllegalArgumentException("Unknown pattern letter: " + cur);
}
@@ -1843,7 +1847,10 @@
}
break;
case 'c':
- if (count == 2) {
+ if (count == 1) {
+ appendValue(new WeekBasedFieldPrinterParser(cur, count, count, count));
+ break;
+ } else if (count == 2) {
throw new IllegalArgumentException("Invalid pattern \"cc\"");
}
/*fallthrough*/
@@ -1858,8 +1865,8 @@
switch (count) {
case 1:
case 2:
- if (cur == 'c' || cur == 'e') {
- appendInternal(new WeekBasedFieldPrinterParser(cur, count));
+ if (cur == 'e') {
+ appendValue(new WeekBasedFieldPrinterParser(cur, count, count, count));
} else if (cur == 'E') {
appendText(field, TextStyle.SHORT);
} else {
@@ -4770,8 +4777,9 @@
* the field is to be printed or parsed.
* The locale is needed to select the proper WeekFields from which
* the field for day-of-week, week-of-month, or week-of-year is selected.
+ * Hence the inherited field NumberPrinterParser.field is unused.
*/
- static final class WeekBasedFieldPrinterParser implements DateTimePrinterParser {
+ static final class WeekBasedFieldPrinterParser extends NumberPrinterParser {
private char chr;
private int count;
@@ -4780,12 +4788,55 @@
*
* @param chr the pattern format letter that added this PrinterParser.
* @param count the repeat count of the format letter
+ * @param minWidth the minimum field width, from 1 to 19
+ * @param maxWidth the maximum field width, from minWidth to 19
*/
- WeekBasedFieldPrinterParser(char chr, int count) {
+ WeekBasedFieldPrinterParser(char chr, int count, int minWidth, int maxWidth) {
+ this(chr, count, minWidth, maxWidth, 0);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param chr the pattern format letter that added this PrinterParser.
+ * @param count the repeat count of the format letter
+ * @param minWidth the minimum field width, from 1 to 19
+ * @param maxWidth the maximum field width, from minWidth to 19
+ * @param subsequentWidth the width of subsequent non-negative numbers, 0 or greater,
+ * -1 if fixed width due to active adjacent parsing
+ */
+ WeekBasedFieldPrinterParser(char chr, int count, int minWidth, int maxWidth,
+ int subsequentWidth) {
+ super(null, minWidth, maxWidth, SignStyle.NOT_NEGATIVE, subsequentWidth);
this.chr = chr;
this.count = count;
}
+ /**
+ * Returns a new instance with fixed width flag set.
+ *
+ * @return a new updated printer-parser, not null
+ */
+ @Override
+ WeekBasedFieldPrinterParser withFixedWidth() {
+ if (subsequentWidth == -1) {
+ return this;
+ }
+ return new WeekBasedFieldPrinterParser(chr, count, minWidth, maxWidth, -1);
+ }
+
+ /**
+ * Returns a new instance with an updated subsequent width.
+ *
+ * @param subsequentWidth the width of subsequent non-negative numbers, 0 or greater
+ * @return a new updated printer-parser, not null
+ */
+ @Override
+ WeekBasedFieldPrinterParser withSubsequentWidth(int subsequentWidth) {
+ return new WeekBasedFieldPrinterParser(chr, count, minWidth, maxWidth,
+ this.subsequentWidth + subsequentWidth);
+ }
+
@Override
public boolean format(DateTimePrintContext context, StringBuilder buf) {
return printerParser(context.getLocale()).format(context, buf);
@@ -4810,10 +4861,12 @@
case 'Y':
field = weekDef.weekBasedYear();
if (count == 2) {
- return new ReducedPrinterParser(field, 2, 2, 0, ReducedPrinterParser.BASE_DATE, 0);
+ return new ReducedPrinterParser(field, 2, 2, 0, ReducedPrinterParser.BASE_DATE,
+ this.subsequentWidth);
} else {
return new NumberPrinterParser(field, count, 19,
- (count < 4) ? SignStyle.NORMAL : SignStyle.EXCEEDS_PAD, -1);
+ (count < 4) ? SignStyle.NORMAL : SignStyle.EXCEEDS_PAD,
+ this.subsequentWidth);
}
case 'e':
case 'c':
@@ -4828,7 +4881,8 @@
default:
throw new IllegalStateException("unreachable");
}
- return new NumberPrinterParser(field, (count == 2 ? 2 : 1), 2, SignStyle.NOT_NEGATIVE);
+ return new NumberPrinterParser(field, minWidth, maxWidth, SignStyle.NOT_NEGATIVE,
+ this.subsequentWidth);
}
@Override
--- a/jdk/src/java.base/share/classes/java/util/ArrayDeque.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/ArrayDeque.java Thu Dec 22 18:48:53 2016 +0000
@@ -146,16 +146,16 @@
if (jump < needed
|| (newCapacity = (oldCapacity + jump)) - MAX_ARRAY_SIZE > 0)
newCapacity = newCapacity(needed, jump);
- elements = Arrays.copyOf(elements, newCapacity);
+ final Object[] es = elements = Arrays.copyOf(elements, newCapacity);
// Exceptionally, here tail == head needs to be disambiguated
- if (tail < head || (tail == head && elements[head] != null)) {
+ if (tail < head || (tail == head && es[head] != null)) {
// wrap around; slide first leg forward to end of array
int newSpace = newCapacity - oldCapacity;
- System.arraycopy(elements, head,
- elements, head + newSpace,
+ System.arraycopy(es, head,
+ es, head + newSpace,
oldCapacity - head);
- Arrays.fill(elements, head, head + newSpace, null);
- head += newSpace;
+ for (int i = head, to = (head += newSpace); i < to; i++)
+ es[i] = null;
}
}
@@ -873,6 +873,9 @@
}
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
final Object[] es = elements;
@@ -1035,11 +1038,14 @@
/**
* Nulls out slots starting at array index i, upto index end.
+ * Condition i == end means "empty" - nothing to do.
*/
private static void circularClear(Object[] es, int i, int end) {
+ // assert 0 <= i && i < es.length;
+ // assert 0 <= end && end < es.length;
for (int to = (i <= end) ? end : es.length;
; i = 0, to = end) {
- Arrays.fill(es, i, to, null);
+ for (; i < to; i++) es[i] = null;
if (to == end) break;
}
}
--- a/jdk/src/java.base/share/classes/java/util/ArrayList.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/ArrayList.java Thu Dec 22 18:48:53 2016 +0000
@@ -576,8 +576,9 @@
*/
public void clear() {
modCount++;
- Arrays.fill(elementData, 0, size, null);
- size = 0;
+ final Object[] es = elementData;
+ for (int to = size, i = size = 0; i < to; i++)
+ es[i] = null;
}
/**
@@ -665,10 +666,14 @@
outOfBoundsMsg(fromIndex, toIndex));
}
modCount++;
- final Object[] es = elementData;
- final int oldSize = size;
- System.arraycopy(es, toIndex, es, fromIndex, oldSize - toIndex);
- Arrays.fill(es, size -= (toIndex - fromIndex), oldSize, null);
+ shiftTailOverGap(elementData, fromIndex, toIndex);
+ }
+
+ /** Erases the gap from lo to hi, by sliding down following elements. */
+ private void shiftTailOverGap(Object[] es, int lo, int hi) {
+ System.arraycopy(es, hi, es, lo, size - hi);
+ for (int to = size, i = (size -= hi - lo); i < to; i++)
+ es[i] = null;
}
/**
@@ -756,25 +761,25 @@
w += end - r;
throw ex;
} finally {
- final int oldSize = size, deleted = end - w;
- modCount += deleted;
- System.arraycopy(es, end, es, w, oldSize - end);
- Arrays.fill(es, size -= deleted, oldSize, null);
+ modCount += end - w;
+ shiftTailOverGap(es, w, end);
}
}
return modified;
}
/**
- * Save the state of the {@code ArrayList} instance to a stream (that
- * is, serialize it).
+ * Saves the state of the {@code ArrayList} instance to a stream
+ * (that is, serializes it).
*
+ * @param s the stream
+ * @throws java.io.IOException if an I/O error occurs
* @serialData The length of the array backing the {@code ArrayList}
* instance is emitted (int), followed by all of its elements
* (each an {@code Object}) in the proper order.
*/
private void writeObject(java.io.ObjectOutputStream s)
- throws java.io.IOException{
+ throws java.io.IOException {
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();
@@ -793,8 +798,12 @@
}
/**
- * Reconstitute the {@code ArrayList} instance from a stream (that is,
- * deserialize it).
+ * Reconstitutes the {@code ArrayList} instance from a stream (that is,
+ * deserializes it).
+ * @param s the stream
+ * @throws ClassNotFoundException if the class of a serialized object
+ * could not be found
+ * @throws java.io.IOException if an I/O error occurs
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
@@ -1285,9 +1294,8 @@
public Spliterator<E> spliterator() {
checkForComodification();
- // ArrayListSpliterator is not used because late-binding logic
- // is different here
- return new Spliterator<>() {
+ // ArrayListSpliterator not used here due to late-binding
+ return new Spliterator<E>() {
private int index = offset; // current index, modified on advance/split
private int fence = -1; // -1 until used; then one past last index
private int expectedModCount; // initialized when fence set
@@ -1301,12 +1309,11 @@
return hi;
}
- public ArrayListSpliterator<E> trySplit() {
+ public ArrayList<E>.ArrayListSpliterator trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
- // ArrayListSpliterator could be used here as the source is already bound
+ // ArrayListSpliterator can be used here as the source is already bound
return (lo >= mid) ? null : // divide range in half unless too small
- new ArrayListSpliterator<>(root, lo, index = mid,
- expectedModCount);
+ root.new ArrayListSpliterator(lo, index = mid, expectedModCount);
}
public boolean tryAdvance(Consumer<? super E> action) {
@@ -1348,7 +1355,7 @@
}
public long estimateSize() {
- return (long) (getFence() - index);
+ return getFence() - index;
}
public int characteristics() {
@@ -1358,6 +1365,9 @@
}
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
@@ -1385,11 +1395,11 @@
*/
@Override
public Spliterator<E> spliterator() {
- return new ArrayListSpliterator<>(this, 0, -1, 0);
+ return new ArrayListSpliterator(0, -1, 0);
}
/** Index-based split-by-two, lazily initialized Spliterator */
- static final class ArrayListSpliterator<E> implements Spliterator<E> {
+ final class ArrayListSpliterator implements Spliterator<E> {
/*
* If ArrayLists were immutable, or structurally immutable (no
@@ -1423,15 +1433,12 @@
* these streamlinings.
*/
- private final ArrayList<E> list;
private int index; // current index, modified on advance/split
private int fence; // -1 until used; then one past last index
private int expectedModCount; // initialized when fence set
- /** Create new spliterator covering the given range */
- ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
- int expectedModCount) {
- this.list = list; // OK if null unless traversed
+ /** Creates new spliterator covering the given range. */
+ ArrayListSpliterator(int origin, int fence, int expectedModCount) {
this.index = origin;
this.fence = fence;
this.expectedModCount = expectedModCount;
@@ -1439,23 +1446,17 @@
private int getFence() { // initialize fence to size on first use
int hi; // (a specialized variant appears in method forEach)
- ArrayList<E> lst;
if ((hi = fence) < 0) {
- if ((lst = list) == null)
- hi = fence = 0;
- else {
- expectedModCount = lst.modCount;
- hi = fence = lst.size;
- }
+ expectedModCount = modCount;
+ hi = fence = size;
}
return hi;
}
- public ArrayListSpliterator<E> trySplit() {
+ public ArrayListSpliterator trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid) ? null : // divide range in half unless too small
- new ArrayListSpliterator<>(list, lo, index = mid,
- expectedModCount);
+ new ArrayListSpliterator(lo, index = mid, expectedModCount);
}
public boolean tryAdvance(Consumer<? super E> action) {
@@ -1464,9 +1465,9 @@
int hi = getFence(), i = index;
if (i < hi) {
index = i + 1;
- @SuppressWarnings("unchecked") E e = (E)list.elementData[i];
+ @SuppressWarnings("unchecked") E e = (E)elementData[i];
action.accept(e);
- if (list.modCount != expectedModCount)
+ if (modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
@@ -1475,13 +1476,13 @@
public void forEachRemaining(Consumer<? super E> action) {
int i, hi, mc; // hoist accesses and checks from loop
- ArrayList<E> lst; Object[] a;
+ Object[] a;
if (action == null)
throw new NullPointerException();
- if ((lst = list) != null && (a = lst.elementData) != null) {
+ if ((a = elementData) != null) {
if ((hi = fence) < 0) {
- mc = lst.modCount;
- hi = lst.size;
+ mc = modCount;
+ hi = size;
}
else
mc = expectedModCount;
@@ -1490,7 +1491,7 @@
@SuppressWarnings("unchecked") E e = (E) a[i];
action.accept(e);
}
- if (lst.modCount == mc)
+ if (modCount == mc)
return;
}
}
@@ -1498,7 +1499,7 @@
}
public long estimateSize() {
- return (long) (getFence() - index);
+ return getFence() - index;
}
public int characteristics() {
@@ -1518,6 +1519,9 @@
return (bits[i >> 6] & (1L << i)) == 0;
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
@Override
public boolean removeIf(Predicate<? super E> filter) {
return removeIf(filter, 0, size);
@@ -1552,9 +1556,7 @@
for (i = beg; i < end; i++)
if (isClear(deathRow, i - beg))
es[w++] = es[i];
- final int oldSize = size;
- System.arraycopy(es, end, es, w, oldSize - end);
- Arrays.fill(es, size -= (end - w), oldSize, null);
+ shiftTailOverGap(es, w, end);
return true;
} else {
if (modCount != expectedModCount)
--- a/jdk/src/java.base/share/classes/java/util/PriorityQueue.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/PriorityQueue.java Thu Dec 22 18:48:53 2016 +0000
@@ -522,6 +522,8 @@
*/
private int expectedModCount = modCount;
+ Itr() {} // prevent access constructor creation
+
public boolean hasNext() {
return cursor < size ||
(forgetMeNot != null && !forgetMeNot.isEmpty());
@@ -631,7 +633,7 @@
* promoting x up the tree until it is greater than or equal to
* its parent, or is the root.
*
- * To simplify and speed up coercions and comparisons. the
+ * To simplify and speed up coercions and comparisons, the
* Comparable and Comparator versions are separated into different
* methods that are otherwise identical. (Similarly for siftDown.)
*
@@ -727,11 +729,18 @@
/**
* Establishes the heap invariant (described above) in the entire tree,
* assuming nothing about the order of the elements prior to the call.
+ * This classic algorithm due to Floyd (1964) is known to be O(size).
*/
@SuppressWarnings("unchecked")
private void heapify() {
- for (int i = (size >>> 1) - 1; i >= 0; i--)
- siftDown(i, (E) queue[i]);
+ final Object[] es = queue;
+ final int half = (size >>> 1) - 1;
+ if (comparator == null)
+ for (int i = half; i >= 0; i--)
+ siftDownComparable(i, (E) es[i]);
+ else
+ for (int i = half; i >= 0; i--)
+ siftDownUsingComparator(i, (E) es[i]);
}
/**
@@ -812,23 +821,16 @@
* @since 1.8
*/
public final Spliterator<E> spliterator() {
- return new PriorityQueueSpliterator<>(this, 0, -1, 0);
+ return new PriorityQueueSpliterator(0, -1, 0);
}
- static final class PriorityQueueSpliterator<E> implements Spliterator<E> {
- /*
- * This is very similar to ArrayList Spliterator, except for
- * extra null checks.
- */
- private final PriorityQueue<E> pq;
+ final class PriorityQueueSpliterator implements Spliterator<E> {
private int index; // current index, modified on advance/split
private int fence; // -1 until first use
private int expectedModCount; // initialized when fence set
/** Creates new spliterator covering the given range. */
- PriorityQueueSpliterator(PriorityQueue<E> pq, int origin, int fence,
- int expectedModCount) {
- this.pq = pq;
+ PriorityQueueSpliterator(int origin, int fence, int expectedModCount) {
this.index = origin;
this.fence = fence;
this.expectedModCount = expectedModCount;
@@ -837,68 +839,54 @@
private int getFence() { // initialize fence to size on first use
int hi;
if ((hi = fence) < 0) {
- expectedModCount = pq.modCount;
- hi = fence = pq.size;
+ expectedModCount = modCount;
+ hi = fence = size;
}
return hi;
}
- public PriorityQueueSpliterator<E> trySplit() {
+ public PriorityQueueSpliterator trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid) ? null :
- new PriorityQueueSpliterator<>(pq, lo, index = mid,
- expectedModCount);
+ new PriorityQueueSpliterator(lo, index = mid, expectedModCount);
}
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> action) {
- int i, hi, mc; // hoist accesses and checks from loop
- PriorityQueue<E> q; Object[] a;
if (action == null)
throw new NullPointerException();
- if ((q = pq) != null && (a = q.queue) != null) {
- if ((hi = fence) < 0) {
- mc = q.modCount;
- hi = q.size;
- }
- else
- mc = expectedModCount;
- if ((i = index) >= 0 && (index = hi) <= a.length) {
- for (E e;; ++i) {
- if (i < hi) {
- if ((e = (E) a[i]) == null) // must be CME
- break;
- action.accept(e);
- }
- else if (q.modCount != mc)
- break;
- else
- return;
- }
- }
+ if (fence < 0) { fence = size; expectedModCount = modCount; }
+ final Object[] a = queue;
+ int i, hi; E e;
+ for (i = index, index = hi = fence; i < hi; i++) {
+ if ((e = (E) a[i]) == null)
+ break; // must be CME
+ action.accept(e);
}
- throw new ConcurrentModificationException();
+ if (modCount != expectedModCount)
+ throw new ConcurrentModificationException();
}
+ @SuppressWarnings("unchecked")
public boolean tryAdvance(Consumer<? super E> action) {
if (action == null)
throw new NullPointerException();
- int hi = getFence(), lo = index;
- if (lo >= 0 && lo < hi) {
- index = lo + 1;
- @SuppressWarnings("unchecked") E e = (E)pq.queue[lo];
- if (e == null)
+ if (fence < 0) { fence = size; expectedModCount = modCount; }
+ int i;
+ if ((i = index) < fence) {
+ index = i + 1;
+ E e;
+ if ((e = (E) queue[i]) == null
+ || modCount != expectedModCount)
throw new ConcurrentModificationException();
action.accept(e);
- if (pq.modCount != expectedModCount)
- throw new ConcurrentModificationException();
return true;
}
return false;
}
public long estimateSize() {
- return (long) (getFence() - index);
+ return getFence() - index;
}
public int characteristics() {
--- a/jdk/src/java.base/share/classes/java/util/ResourceBundle.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/ResourceBundle.java Thu Dec 22 18:48:53 2016 +0000
@@ -2942,17 +2942,6 @@
script = "Hans";
break;
}
- } else if (script.length() > 0 && region.length() == 0) {
- // Supply region(country) for users who still package Chinese
- // bundles using old convension.
- switch (script) {
- case "Hans":
- region = "CN";
- break;
- case "Hant":
- region = "TW";
- break;
- }
}
}
@@ -2983,6 +2972,21 @@
}
if (script.length() > 0) {
list.add(Locale.getInstance(language, script, "", "", null));
+ // Special handling for Chinese
+ if (language.equals("zh")) {
+ if (region.length() == 0) {
+ // Supply region(country) for users who still package Chinese
+ // bundles using old convension.
+ switch (script) {
+ case "Hans":
+ region = "CN";
+ break;
+ case "Hant":
+ region = "TW";
+ break;
+ }
+ }
+ }
// With script, after truncating variant, region and script,
// start over without script.
--- a/jdk/src/java.base/share/classes/java/util/SplittableRandom.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/SplittableRandom.java Thu Dec 22 18:48:53 2016 +0000
@@ -375,7 +375,7 @@
* may, and typically does, vary across program invocations.
*/
public SplittableRandom() { // emulate defaultGen.split()
- long s = defaultGen.getAndAdd(2 * GOLDEN_GAMMA);
+ long s = defaultGen.getAndAdd(GOLDEN_GAMMA << 1);
this.seed = mix64(s);
this.gamma = mixGamma(s + GOLDEN_GAMMA);
}
--- a/jdk/src/java.base/share/classes/java/util/Vector.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/Vector.java Thu Dec 22 18:48:53 2016 +0000
@@ -306,9 +306,9 @@
modCount++;
if (newSize > elementData.length)
grow(newSize);
- for (int i = newSize; i < elementCount; i++)
- elementData[i] = null;
- elementCount = newSize;
+ final Object[] es = elementData;
+ for (int to = elementCount, i = elementCount = newSize; i < to; i++)
+ es[i] = null;
}
/**
@@ -675,9 +675,10 @@
* method (which is part of the {@link List} interface).
*/
public synchronized void removeAllElements() {
- Arrays.fill(elementData, 0, elementCount, null);
+ final Object[] es = elementData;
+ for (int to = elementCount, i = elementCount = 0; i < to; i++)
+ es[i] = null;
modCount++;
- elementCount = 0;
}
/**
@@ -980,6 +981,9 @@
return bulkRemove(e -> !c.contains(e));
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
@Override
public boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
@@ -1024,7 +1028,8 @@
for (i = beg; i < end; i++)
if (isClear(deathRow, i - beg))
es[w++] = es[i];
- Arrays.fill(es, elementCount = w, end, null);
+ for (i = elementCount = w; i < end; i++)
+ es[i] = null;
return true;
} else {
if (modCount != expectedModCount)
@@ -1152,19 +1157,25 @@
* (If {@code toIndex==fromIndex}, this operation has no effect.)
*/
protected synchronized void removeRange(int fromIndex, int toIndex) {
- final Object[] es = elementData;
- final int oldSize = elementCount;
- System.arraycopy(es, toIndex, es, fromIndex, oldSize - toIndex);
+ modCount++;
+ shiftTailOverGap(elementData, fromIndex, toIndex);
+ }
- modCount++;
- Arrays.fill(es, elementCount -= (toIndex - fromIndex), oldSize, null);
+ /** Erases the gap from lo to hi, by sliding down following elements. */
+ private void shiftTailOverGap(Object[] es, int lo, int hi) {
+ System.arraycopy(es, hi, es, lo, elementCount - hi);
+ for (int to = elementCount, i = (elementCount -= hi - lo); i < to; i++)
+ es[i] = null;
}
/**
- * Save the state of the {@code Vector} instance to a stream (that
- * is, serialize it).
+ * Saves the state of the {@code Vector} instance to a stream
+ * (that is, serializes it).
* This method performs synchronization to ensure the consistency
* of the serialized data.
+ *
+ * @param s the stream
+ * @throws java.io.IOException if an I/O error occurs
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
@@ -1337,6 +1348,9 @@
}
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
@Override
public synchronized void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
@@ -1349,6 +1363,9 @@
throw new ConcurrentModificationException();
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
@Override
public synchronized void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
@@ -1387,21 +1404,19 @@
*/
@Override
public Spliterator<E> spliterator() {
- return new VectorSpliterator<>(this, null, 0, -1, 0);
+ return new VectorSpliterator(null, 0, -1, 0);
}
/** Similar to ArrayList Spliterator */
- static final class VectorSpliterator<E> implements Spliterator<E> {
- private final Vector<E> list;
+ final class VectorSpliterator implements Spliterator<E> {
private Object[] array;
private int index; // current index, modified on advance/split
private int fence; // -1 until used; then one past last index
private int expectedModCount; // initialized when fence set
- /** Create new spliterator covering the given range */
- VectorSpliterator(Vector<E> list, Object[] array, int origin, int fence,
+ /** Creates new spliterator covering the given range. */
+ VectorSpliterator(Object[] array, int origin, int fence,
int expectedModCount) {
- this.list = list;
this.array = array;
this.index = origin;
this.fence = fence;
@@ -1411,10 +1426,10 @@
private int getFence() { // initialize on first use
int hi;
if ((hi = fence) < 0) {
- synchronized (list) {
- array = list.elementData;
- expectedModCount = list.modCount;
- hi = fence = list.elementCount;
+ synchronized (Vector.this) {
+ array = elementData;
+ expectedModCount = modCount;
+ hi = fence = elementCount;
}
}
return hi;
@@ -1423,8 +1438,7 @@
public Spliterator<E> trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid) ? null :
- new VectorSpliterator<>(list, array, lo, index = mid,
- expectedModCount);
+ new VectorSpliterator(array, lo, index = mid, expectedModCount);
}
@SuppressWarnings("unchecked")
@@ -1435,7 +1449,7 @@
if (getFence() > (i = index)) {
index = i + 1;
action.accept((E)array[i]);
- if (list.modCount != expectedModCount)
+ if (modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
@@ -1444,28 +1458,15 @@
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> action) {
- int i, hi; // hoist accesses and checks from loop
- Vector<E> lst; Object[] a;
if (action == null)
throw new NullPointerException();
- if ((lst = list) != null) {
- if ((hi = fence) < 0) {
- synchronized (lst) {
- expectedModCount = lst.modCount;
- a = array = lst.elementData;
- hi = fence = lst.elementCount;
- }
- }
- else
- a = array;
- if (a != null && (i = index) >= 0 && (index = hi) <= a.length) {
- while (i < hi)
- action.accept((E) a[i++]);
- if (lst.modCount == expectedModCount)
- return;
- }
- }
- throw new ConcurrentModificationException();
+ final int hi = getFence();
+ final Object[] a = array;
+ int i;
+ for (i = index, index = hi; i < hi; i++)
+ action.accept((E) a[i]);
+ if (modCount != expectedModCount)
+ throw new ConcurrentModificationException();
}
public long estimateSize() {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java Thu Dec 22 18:48:53 2016 +0000
@@ -675,12 +675,14 @@
/**
* Nulls out slots starting at array index i, upto index end.
- * If i == end, the entire array is cleared!
+ * Condition i == end means "full" - the entire array is cleared.
*/
private static void circularClear(Object[] items, int i, int end) {
+ // assert 0 <= i && i < items.length;
+ // assert 0 <= end && end < items.length;
for (int to = (i < end) ? end : items.length;
; i = 0, to = end) {
- Arrays.fill(items, i, to, null);
+ for (; i < to; i++) items[i] = null;
if (to == end) break;
}
}
@@ -1011,6 +1013,11 @@
* expected element to remove, in lastItem. Yes, we may fail to
* remove lastItem from the queue if it moved due to an interleaved
* interior remove while in detached mode.
+ *
+ * Method forEachRemaining, added in Java 8, is treated similarly
+ * to hasNext returning false, in that we switch to detached mode,
+ * but we regard it as an even stronger request to "close" this
+ * iteration, and don't bother supporting subsequent remove().
*/
private class Itr implements Iterator<E> {
/** Index to look for new nextItem; NONE at end */
@@ -1432,6 +1439,9 @@
Spliterator.CONCURRENT));
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
final ReentrantLock lock = this.lock;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java Thu Dec 22 18:48:53 2016 +0000
@@ -48,6 +48,7 @@
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;
+import java.util.function.Predicate;
/**
* An unbounded concurrent {@linkplain Deque deque} based on linked nodes.
@@ -864,8 +865,8 @@
public E peekFirst() {
for (Node<E> p = first(); p != null; p = succ(p)) {
- E item = p.item;
- if (item != null)
+ final E item;
+ if ((item = p.item) != null)
return item;
}
return null;
@@ -873,8 +874,8 @@
public E peekLast() {
for (Node<E> p = last(); p != null; p = pred(p)) {
- E item = p.item;
- if (item != null)
+ final E item;
+ if ((item = p.item) != null)
return item;
}
return null;
@@ -896,8 +897,9 @@
public E pollFirst() {
for (Node<E> p = first(); p != null; p = succ(p)) {
- E item = p.item;
- if (item != null && ITEM.compareAndSet(p, item, null)) {
+ final E item;
+ if ((item = p.item) != null
+ && ITEM.compareAndSet(p, item, null)) {
unlink(p);
return item;
}
@@ -907,8 +909,9 @@
public E pollLast() {
for (Node<E> p = last(); p != null; p = pred(p)) {
- E item = p.item;
- if (item != null && ITEM.compareAndSet(p, item, null)) {
+ final E item;
+ if ((item = p.item) != null
+ && ITEM.compareAndSet(p, item, null)) {
unlink(p);
return item;
}
@@ -993,9 +996,10 @@
public boolean removeFirstOccurrence(Object o) {
Objects.requireNonNull(o);
for (Node<E> p = first(); p != null; p = succ(p)) {
- E item = p.item;
- if (item != null && o.equals(item) &&
- ITEM.compareAndSet(p, item, null)) {
+ final E item;
+ if ((item = p.item) != null
+ && o.equals(item)
+ && ITEM.compareAndSet(p, item, null)) {
unlink(p);
return true;
}
@@ -1018,9 +1022,10 @@
public boolean removeLastOccurrence(Object o) {
Objects.requireNonNull(o);
for (Node<E> p = last(); p != null; p = pred(p)) {
- E item = p.item;
- if (item != null && o.equals(item) &&
- ITEM.compareAndSet(p, item, null)) {
+ final E item;
+ if ((item = p.item) != null
+ && o.equals(item)
+ && ITEM.compareAndSet(p, item, null)) {
unlink(p);
return true;
}
@@ -1039,8 +1044,8 @@
public boolean contains(Object o) {
if (o != null) {
for (Node<E> p = first(); p != null; p = succ(p)) {
- E item = p.item;
- if (item != null && o.equals(item))
+ final E item;
+ if ((item = p.item) != null && o.equals(item))
return true;
}
}
@@ -1181,8 +1186,8 @@
int charLength = 0;
int size = 0;
for (Node<E> p = first(); p != null;) {
- E item = p.item;
- if (item != null) {
+ final E item;
+ if ((item = p.item) != null) {
if (a == null)
a = new String[4];
else if (size == a.length)
@@ -1207,8 +1212,8 @@
restartFromHead: for (;;) {
int size = 0;
for (Node<E> p = first(); p != null;) {
- E item = p.item;
- if (item != null) {
+ final E item;
+ if ((item = p.item) != null) {
if (x == null)
x = new Object[4];
else if (size == x.length)
@@ -1360,8 +1365,8 @@
nextItem = null;
break;
}
- E item = p.item;
- if (item != null) {
+ final E item;
+ if ((item = p.item) != null) {
nextNode = p;
nextItem = item;
break;
@@ -1391,36 +1396,33 @@
/** Forward iterator */
private class Itr extends AbstractItr {
+ Itr() {} // prevent access constructor creation
Node<E> startNode() { return first(); }
Node<E> nextNode(Node<E> p) { return succ(p); }
}
/** Descending iterator */
private class DescendingItr extends AbstractItr {
+ DescendingItr() {} // prevent access constructor creation
Node<E> startNode() { return last(); }
Node<E> nextNode(Node<E> p) { return pred(p); }
}
/** A customized variant of Spliterators.IteratorSpliterator */
- static final class CLDSpliterator<E> implements Spliterator<E> {
+ final class CLDSpliterator implements Spliterator<E> {
static final int MAX_BATCH = 1 << 25; // max batch array size;
- final ConcurrentLinkedDeque<E> queue;
Node<E> current; // current node; null until initialized
int batch; // batch size for splits
boolean exhausted; // true when no more nodes
- CLDSpliterator(ConcurrentLinkedDeque<E> queue) {
- this.queue = queue;
- }
public Spliterator<E> trySplit() {
Node<E> p;
- final ConcurrentLinkedDeque<E> q = this.queue;
int b = batch;
int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
if (!exhausted &&
- ((p = current) != null || (p = q.first()) != null)) {
+ ((p = current) != null || (p = first()) != null)) {
if (p.item == null && p == (p = p.next))
- current = p = q.first();
+ current = p = first();
if (p != null && p.next != null) {
Object[] a = new Object[n];
int i = 0;
@@ -1428,7 +1430,7 @@
if ((a[i] = p.item) != null)
++i;
if (p == (p = p.next))
- p = q.first();
+ p = first();
} while (p != null && i < n);
if ((current = p) == null)
exhausted = true;
@@ -1447,14 +1449,13 @@
public void forEachRemaining(Consumer<? super E> action) {
Node<E> p;
if (action == null) throw new NullPointerException();
- final ConcurrentLinkedDeque<E> q = this.queue;
if (!exhausted &&
- ((p = current) != null || (p = q.first()) != null)) {
+ ((p = current) != null || (p = first()) != null)) {
exhausted = true;
do {
E e = p.item;
if (p == (p = p.next))
- p = q.first();
+ p = first();
if (e != null)
action.accept(e);
} while (p != null);
@@ -1464,14 +1465,13 @@
public boolean tryAdvance(Consumer<? super E> action) {
Node<E> p;
if (action == null) throw new NullPointerException();
- final ConcurrentLinkedDeque<E> q = this.queue;
if (!exhausted &&
- ((p = current) != null || (p = q.first()) != null)) {
+ ((p = current) != null || (p = first()) != null)) {
E e;
do {
e = p.item;
if (p == (p = p.next))
- p = q.first();
+ p = first();
} while (e == null && p != null);
if ((current = p) == null)
exhausted = true;
@@ -1508,7 +1508,7 @@
* @since 1.8
*/
public Spliterator<E> spliterator() {
- return new CLDSpliterator<E>(this);
+ return new CLDSpliterator();
}
/**
@@ -1527,8 +1527,8 @@
// Write out all elements in the proper order.
for (Node<E> p = first(); p != null; p = succ(p)) {
- E item = p.item;
- if (item != null)
+ final E item;
+ if ((item = p.item) != null)
s.writeObject(item);
}
@@ -1563,6 +1563,57 @@
initHeadTail(h, t);
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean removeIf(Predicate<? super E> filter) {
+ Objects.requireNonNull(filter);
+ return bulkRemove(filter);
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean removeAll(Collection<?> c) {
+ Objects.requireNonNull(c);
+ return bulkRemove(e -> c.contains(e));
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean retainAll(Collection<?> c) {
+ Objects.requireNonNull(c);
+ return bulkRemove(e -> !c.contains(e));
+ }
+
+ /** Implementation of bulk remove methods. */
+ private boolean bulkRemove(Predicate<? super E> filter) {
+ boolean removed = false;
+ for (Node<E> p = first(), succ; p != null; p = succ) {
+ succ = succ(p);
+ final E item;
+ if ((item = p.item) != null
+ && filter.test(item)
+ && ITEM.compareAndSet(p, item, null)) {
+ unlink(p);
+ removed = true;
+ }
+ }
+ return removed;
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void forEach(Consumer<? super E> action) {
+ Objects.requireNonNull(action);
+ E item;
+ for (Node<E> p = first(); p != null; p = succ(p))
+ if ((item = p.item) != null)
+ action.accept(item);
+ }
+
// VarHandle mechanics
private static final VarHandle HEAD;
private static final VarHandle TAIL;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java Thu Dec 22 18:48:53 2016 +0000
@@ -47,6 +47,7 @@
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;
+import java.util.function.Predicate;
/**
* An unbounded thread-safe {@linkplain Queue queue} based on linked nodes.
@@ -112,7 +113,7 @@
/*
* This is a modification of the Michael & Scott algorithm,
* adapted for a garbage-collected environment, with support for
- * interior node deletion (to support remove(Object)). For
+ * interior node deletion (to support e.g. remove(Object)). For
* explanation, read the paper.
*
* Note that like most non-blocking algorithms in this package,
@@ -160,12 +161,13 @@
* it is possible for tail to lag behind head (why not)?
*
* CASing a Node's item reference to null atomically removes the
- * element from the queue. Iterators skip over Nodes with null
- * items. Prior implementations of this class had a race between
- * poll() and remove(Object) where the same element would appear
- * to be successfully removed by two concurrent operations. The
- * method remove(Object) also lazily unlinks deleted Nodes, but
- * this is merely an optimization.
+ * element from the queue, leaving a "dead" node that should later
+ * be unlinked (but unlinking is merely an optimization).
+ * Interior element removal methods (other than Iterator.remove())
+ * keep track of the predecessor node during traversal so that the
+ * node can be CAS-unlinked. Some traversal methods try to unlink
+ * any deleted nodes encountered during traversal. See comments
+ * in bulkRemove.
*
* When constructing a Node (before enqueuing it) we avoid paying
* for a volatile write to item. This allows the cost of enqueue
@@ -290,6 +292,21 @@
}
/**
+ * Tries to CAS pred.next (or head, if pred is null) from c to p.
+ */
+ private boolean tryCasSuccessor(Node<E> pred, Node<E> c, Node<E> p) {
+ // assert c.item == null;
+ // assert c != p;
+ if (pred != null)
+ return NEXT.compareAndSet(pred, c, p);
+ if (HEAD.compareAndSet(this, c, p)) {
+ NEXT.setRelease(c, c);
+ return true;
+ }
+ return false;
+ }
+
+ /**
* Inserts the specified element at the tail of this queue.
* As the queue is unbounded, this method will never return {@code false}.
*
@@ -326,12 +343,11 @@
}
public E poll() {
- restartFromHead:
- for (;;) {
- for (Node<E> h = head, p = h, q;;) {
- E item = p.item;
-
- if (item != null && ITEM.compareAndSet(p, item, null)) {
+ restartFromHead: for (;;) {
+ for (Node<E> h = head, p = h, q;; p = q) {
+ final E item;
+ if ((item = p.item) != null
+ && ITEM.compareAndSet(p, item, null)) {
// Successful CAS is the linearization point
// for item to be removed from this queue.
if (p != h) // hop two nodes at a time
@@ -344,25 +360,21 @@
}
else if (p == q)
continue restartFromHead;
- else
- p = q;
}
}
}
public E peek() {
- restartFromHead:
- for (;;) {
- for (Node<E> h = head, p = h, q;;) {
- E item = p.item;
- if (item != null || (q = p.next) == null) {
+ restartFromHead: for (;;) {
+ for (Node<E> h = head, p = h, q;; p = q) {
+ final E item;
+ if ((item = p.item) != null
+ || (q = p.next) == null) {
updateHead(h, p);
return item;
}
else if (p == q)
continue restartFromHead;
- else
- p = q;
}
}
}
@@ -376,9 +388,8 @@
* of losing a race to a concurrent poll().
*/
Node<E> first() {
- restartFromHead:
- for (;;) {
- for (Node<E> h = head, p = h, q;;) {
+ restartFromHead: for (;;) {
+ for (Node<E> h = head, p = h, q;; p = q) {
boolean hasItem = (p.item != null);
if (hasItem || (q = p.next) == null) {
updateHead(h, p);
@@ -386,8 +397,6 @@
}
else if (p == q)
continue restartFromHead;
- else
- p = q;
}
}
}
@@ -440,14 +449,24 @@
* @return {@code true} if this queue contains the specified element
*/
public boolean contains(Object o) {
- if (o != null) {
- for (Node<E> p = first(); p != null; p = succ(p)) {
- E item = p.item;
- if (item != null && o.equals(item))
+ if (o == null) return false;
+ restartFromHead: for (;;) {
+ for (Node<E> p = head, c = p, pred = null, q; p != null; p = q) {
+ final E item;
+ if ((item = p.item) != null && o.equals(item))
return true;
+ if (c != p && tryCasSuccessor(pred, c, p))
+ c = p;
+ q = p.next;
+ if (item != null || c != p) {
+ pred = p;
+ c = q;
+ }
+ else if (p == q)
+ continue restartFromHead;
}
+ return false;
}
- return false;
}
/**
@@ -462,27 +481,28 @@
* @return {@code true} if this queue changed as a result of the call
*/
public boolean remove(Object o) {
- if (o != null) {
- Node<E> next, pred = null;
- for (Node<E> p = first(); p != null; pred = p, p = next) {
- boolean removed = false;
- E item = p.item;
- if (item != null) {
- if (!o.equals(item)) {
- next = succ(p);
- continue;
- }
- removed = ITEM.compareAndSet(p, item, null);
- }
-
- next = succ(p);
- if (pred != null && next != null) // unlink
- NEXT.weakCompareAndSet(pred, p, next);
+ if (o == null) return false;
+ restartFromHead: for (;;) {
+ for (Node<E> p = head, c = p, pred = null, q; p != null; p = q) {
+ final E item;
+ final boolean removed =
+ (item = p.item) != null
+ && o.equals(item)
+ && ITEM.compareAndSet(p, item, null);
+ if (c != p && tryCasSuccessor(pred, c, p))
+ c = p;
if (removed)
return true;
+ q = p.next;
+ if (item != null || c != p) {
+ pred = p;
+ c = q;
+ }
+ else if (p == q)
+ continue restartFromHead;
}
+ return false;
}
- return false;
}
/**
@@ -553,8 +573,8 @@
int charLength = 0;
int size = 0;
for (Node<E> p = first(); p != null;) {
- E item = p.item;
- if (item != null) {
+ final E item;
+ if ((item = p.item) != null) {
if (a == null)
a = new String[4];
else if (size == a.length)
@@ -579,8 +599,8 @@
restartFromHead: for (;;) {
int size = 0;
for (Node<E> p = first(); p != null;) {
- E item = p.item;
- if (item != null) {
+ final E item;
+ if ((item = p.item) != null) {
if (x == null)
x = new Object[4];
else if (size == x.length)
@@ -697,7 +717,7 @@
restartFromHead: for (;;) {
Node<E> h, p, q;
for (p = h = head;; p = q) {
- E item;
+ final E item;
if ((item = p.item) != null) {
nextNode = p;
nextItem = item;
@@ -762,8 +782,8 @@
// Write out all elements in the proper order.
for (Node<E> p = first(); p != null; p = succ(p)) {
- Object item = p.item;
- if (item != null)
+ final E item;
+ if ((item = p.item) != null)
s.writeObject(item);
}
@@ -801,23 +821,18 @@
}
/** A customized variant of Spliterators.IteratorSpliterator */
- static final class CLQSpliterator<E> implements Spliterator<E> {
+ final class CLQSpliterator implements Spliterator<E> {
static final int MAX_BATCH = 1 << 25; // max batch array size;
- final ConcurrentLinkedQueue<E> queue;
Node<E> current; // current node; null until initialized
int batch; // batch size for splits
boolean exhausted; // true when no more nodes
- CLQSpliterator(ConcurrentLinkedQueue<E> queue) {
- this.queue = queue;
- }
public Spliterator<E> trySplit() {
Node<E> p;
- final ConcurrentLinkedQueue<E> q = this.queue;
int b = batch;
int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
if (!exhausted &&
- ((p = current) != null || (p = q.first()) != null) &&
+ ((p = current) != null || (p = first()) != null) &&
p.next != null) {
Object[] a = new Object[n];
int i = 0;
@@ -825,7 +840,7 @@
if ((a[i] = p.item) != null)
++i;
if (p == (p = p.next))
- p = q.first();
+ p = first();
} while (p != null && i < n);
if ((current = p) == null)
exhausted = true;
@@ -843,14 +858,13 @@
public void forEachRemaining(Consumer<? super E> action) {
Node<E> p;
if (action == null) throw new NullPointerException();
- final ConcurrentLinkedQueue<E> q = this.queue;
if (!exhausted &&
- ((p = current) != null || (p = q.first()) != null)) {
+ ((p = current) != null || (p = first()) != null)) {
exhausted = true;
do {
E e = p.item;
if (p == (p = p.next))
- p = q.first();
+ p = first();
if (e != null)
action.accept(e);
} while (p != null);
@@ -860,14 +874,13 @@
public boolean tryAdvance(Consumer<? super E> action) {
Node<E> p;
if (action == null) throw new NullPointerException();
- final ConcurrentLinkedQueue<E> q = this.queue;
if (!exhausted &&
- ((p = current) != null || (p = q.first()) != null)) {
+ ((p = current) != null || (p = first()) != null)) {
E e;
do {
e = p.item;
if (p == (p = p.next))
- p = q.first();
+ p = first();
} while (e == null && p != null);
if ((current = p) == null)
exhausted = true;
@@ -905,7 +918,100 @@
*/
@Override
public Spliterator<E> spliterator() {
- return new CLQSpliterator<E>(this);
+ return new CLQSpliterator();
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean removeIf(Predicate<? super E> filter) {
+ Objects.requireNonNull(filter);
+ return bulkRemove(filter);
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean removeAll(Collection<?> c) {
+ Objects.requireNonNull(c);
+ return bulkRemove(e -> c.contains(e));
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean retainAll(Collection<?> c) {
+ Objects.requireNonNull(c);
+ return bulkRemove(e -> !c.contains(e));
+ }
+
+ public void clear() {
+ bulkRemove(e -> true);
+ }
+
+ /**
+ * Tolerate this many consecutive dead nodes before CAS-collapsing.
+ * Amortized cost of clear() is (1 + 1/MAX_HOPS) CASes per element.
+ */
+ private static final int MAX_HOPS = 8;
+
+ /** Implementation of bulk remove methods. */
+ private boolean bulkRemove(Predicate<? super E> filter) {
+ boolean removed = false;
+ restartFromHead: for (;;) {
+ int hops = MAX_HOPS;
+ // c will be CASed to collapse intervening dead nodes between
+ // pred (or head if null) and p.
+ for (Node<E> p = head, c = p, pred = null, q; p != null; p = q) {
+ final E item; boolean pAlive;
+ if (pAlive = ((item = p.item) != null)) {
+ if (filter.test(item)) {
+ if (ITEM.compareAndSet(p, item, null))
+ removed = true;
+ pAlive = false;
+ }
+ }
+ if ((q = p.next) == null || pAlive || --hops == 0) {
+ // p might already be self-linked here, but if so:
+ // - CASing head will surely fail
+ // - CASing pred's next will be useless but harmless.
+ if (c != p && tryCasSuccessor(pred, c, p))
+ c = p;
+ // if c != p, CAS failed, so abandon old pred
+ if (pAlive || c != p) {
+ hops = MAX_HOPS;
+ pred = p;
+ c = q;
+ }
+ } else if (p == q)
+ continue restartFromHead;
+ }
+ return removed;
+ }
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void forEach(Consumer<? super E> action) {
+ Objects.requireNonNull(action);
+ restartFromHead: for (;;) {
+ for (Node<E> p = head, c = p, pred = null, q; p != null; p = q) {
+ final E item;
+ if ((item = p.item) != null)
+ action.accept(item);
+ if (c != p && tryCasSuccessor(pred, c, p))
+ c = p;
+ q = p.next;
+ if (item != null || c != p) {
+ pred = p;
+ c = q;
+ }
+ else if (p == q)
+ continue restartFromHead;
+ }
+ return;
+ }
}
// VarHandle mechanics
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java Thu Dec 22 18:48:53 2016 +0000
@@ -793,6 +793,9 @@
}
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
public void forEach(Consumer<? super E> action) {
if (action == null) throw new NullPointerException();
for (Object x : getArray()) {
@@ -801,6 +804,9 @@
}
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
public boolean removeIf(Predicate<? super E> filter) {
if (filter == null) throw new NullPointerException();
return bulkRemove(filter);
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java Thu Dec 22 18:48:53 2016 +0000
@@ -411,10 +411,16 @@
&& compareSets(al.getArray(), (Set<?>) o) == 0);
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
public boolean removeIf(Predicate<? super E> filter) {
return al.removeIf(filter);
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
public void forEach(Consumer<? super E> action) {
al.forEach(action);
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java Thu Dec 22 18:48:53 2016 +0000
@@ -149,7 +149,8 @@
* but no subsequent reset.
*/
private static class Generation {
- boolean broken; // initially false
+ Generation() {} // prevent access constructor creation
+ boolean broken; // initially false
}
/** The lock for guarding barrier entry */
--- a/jdk/src/java.base/share/classes/java/util/concurrent/DelayQueue.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/DelayQueue.java Thu Dec 22 18:48:53 2016 +0000
@@ -547,8 +547,7 @@
public E next() {
if (cursor >= array.length)
throw new NoSuchElementException();
- lastRet = cursor;
- return (E)array[cursor++];
+ return (E)array[lastRet = cursor++];
}
public void remove() {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java Thu Dec 22 18:48:53 2016 +0000
@@ -39,6 +39,7 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.concurrent.locks.Condition;
@@ -740,8 +741,7 @@
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c, int maxElements) {
- if (c == null)
- throw new NullPointerException();
+ Objects.requireNonNull(c);
if (c == this)
throw new IllegalArgumentException();
if (maxElements <= 0)
@@ -986,6 +986,16 @@
}
/**
+ * Used for any element traversal that is not entirely under lock.
+ * Such traversals must handle both:
+ * - dequeued nodes (p.next == p)
+ * - (possibly multiple) interior removed nodes (p.item == null)
+ */
+ Node<E> succ(Node<E> p) {
+ return (p == (p = p.next)) ? first : p;
+ }
+
+ /**
* Returns an iterator over the elements in this deque in proper sequence.
* The elements will be returned in order from first (head) to last (tail).
*
@@ -1024,8 +1034,8 @@
/**
* nextItem holds on to item fields because once we claim that
* an element exists in hasNext(), we must return item read
- * under lock (in advance()) even if it was in the process of
- * being removed when hasNext() was called.
+ * under lock even if it was in the process of being removed
+ * when hasNext() was called.
*/
E nextItem;
@@ -1038,48 +1048,17 @@
abstract Node<E> firstNode();
abstract Node<E> nextNode(Node<E> n);
+ private Node<E> succ(Node<E> p) {
+ return (p == (p = nextNode(p))) ? firstNode() : p;
+ }
+
AbstractItr() {
// set to initial position
final ReentrantLock lock = LinkedBlockingDeque.this.lock;
lock.lock();
try {
- next = firstNode();
- nextItem = (next == null) ? null : next.item;
- } finally {
- lock.unlock();
- }
- }
-
- /**
- * Returns the successor node of the given non-null, but
- * possibly previously deleted, node.
- */
- private Node<E> succ(Node<E> n) {
- // Chains of deleted nodes ending in null or self-links
- // are possible if multiple interior nodes are removed.
- for (;;) {
- Node<E> s = nextNode(n);
- if (s == null)
- return null;
- else if (s.item != null)
- return s;
- else if (s == n)
- return firstNode();
- else
- n = s;
- }
- }
-
- /**
- * Advances next.
- */
- void advance() {
- final ReentrantLock lock = LinkedBlockingDeque.this.lock;
- lock.lock();
- try {
- // assert next != null;
- next = succ(next);
- nextItem = (next == null) ? null : next.item;
+ if ((next = firstNode()) != null)
+ nextItem = next.item;
} finally {
lock.unlock();
}
@@ -1090,14 +1069,65 @@
}
public E next() {
- if (next == null)
+ Node<E> p;
+ if ((p = next) == null)
throw new NoSuchElementException();
- lastRet = next;
+ lastRet = p;
E x = nextItem;
- advance();
+ final ReentrantLock lock = LinkedBlockingDeque.this.lock;
+ lock.lock();
+ try {
+ E e = null;
+ for (p = nextNode(p); p != null && (e = p.item) == null; )
+ p = succ(p);
+ next = p;
+ nextItem = e;
+ } finally {
+ lock.unlock();
+ }
return x;
}
+ public void forEachRemaining(Consumer<? super E> action) {
+ // A variant of forEachFrom
+ Objects.requireNonNull(action);
+ Node<E> p;
+ if ((p = next) == null) return;
+ lastRet = p;
+ next = null;
+ final ReentrantLock lock = LinkedBlockingDeque.this.lock;
+ final int batchSize = 32;
+ Object[] es = null;
+ int n, len = 1;
+ do {
+ lock.lock();
+ try {
+ if (es == null) {
+ p = nextNode(p);
+ for (Node<E> q = p; q != null; q = succ(q))
+ if (q.item != null && ++len == batchSize)
+ break;
+ es = new Object[len];
+ es[0] = nextItem;
+ nextItem = null;
+ n = 1;
+ } else
+ n = 0;
+ for (; p != null && n < len; p = succ(p))
+ if ((es[n] = p.item) != null) {
+ lastRet = p;
+ n++;
+ }
+ } finally {
+ lock.unlock();
+ }
+ for (int i = 0; i < n; i++) {
+ @SuppressWarnings("unchecked") E e = (E) es[i];
+ action.accept(e);
+ }
+ } while (n > 0 && p != null);
+ }
+
public void remove() {
Node<E> n = lastRet;
if (n == null)
@@ -1116,25 +1146,30 @@
/** Forward iterator */
private class Itr extends AbstractItr {
+ Itr() {} // prevent access constructor creation
Node<E> firstNode() { return first; }
Node<E> nextNode(Node<E> n) { return n.next; }
}
/** Descending iterator */
private class DescendingItr extends AbstractItr {
+ DescendingItr() {} // prevent access constructor creation
Node<E> firstNode() { return last; }
Node<E> nextNode(Node<E> n) { return n.prev; }
}
- /** A customized variant of Spliterators.IteratorSpliterator */
+ /**
+ * A customized variant of Spliterators.IteratorSpliterator.
+ * Keep this class in sync with (very similar) LBQSpliterator.
+ */
private final class LBDSpliterator implements Spliterator<E> {
static final int MAX_BATCH = 1 << 25; // max batch array size;
Node<E> current; // current node; null until initialized
int batch; // batch size for splits
boolean exhausted; // true when no more nodes
- long est; // size estimate
+ long est = size(); // size estimate
- LBDSpliterator() { est = size(); }
+ LBDSpliterator() {}
public long estimateSize() { return est; }
@@ -1143,8 +1178,7 @@
int b = batch;
int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
if (!exhausted &&
- (((h = current) != null && h != h.next)
- || (h = first) != null)
+ ((h = current) != null || (h = first) != null)
&& h.next != null) {
Object[] a = new Object[n];
final ReentrantLock lock = LinkedBlockingDeque.this.lock;
@@ -1152,10 +1186,10 @@
Node<E> p = current;
lock.lock();
try {
- if (((p != null && p != p.next) || (p = first) != null)
- && p.item != null)
- for (; p != null && i < n; p = p.next)
- a[i++] = p.item;
+ if (p != null || (p = first) != null)
+ for (; p != null && i < n; p = succ(p))
+ if ((a[i] = p.item) != null)
+ i++;
} finally {
lock.unlock();
}
@@ -1176,51 +1210,39 @@
return null;
}
- public void forEachRemaining(Consumer<? super E> action) {
- if (action == null) throw new NullPointerException();
- if (exhausted)
- return;
- exhausted = true;
- final ReentrantLock lock = LinkedBlockingDeque.this.lock;
- Node<E> p = current;
- current = null;
- do {
+ public boolean tryAdvance(Consumer<? super E> action) {
+ Objects.requireNonNull(action);
+ if (!exhausted) {
E e = null;
+ final ReentrantLock lock = LinkedBlockingDeque.this.lock;
lock.lock();
try {
- if ((p != null && p != p.next) || (p = first) != null) {
- e = p.item;
- p = p.next;
- }
+ Node<E> p;
+ if ((p = current) != null || (p = first) != null)
+ do {
+ e = p.item;
+ p = succ(p);
+ } while (e == null && p != null);
+ exhausted = ((current = p) == null);
} finally {
lock.unlock();
}
- if (e != null)
+ if (e != null) {
action.accept(e);
- } while (p != null);
+ return true;
+ }
+ }
+ return false;
}
- public boolean tryAdvance(Consumer<? super E> action) {
- if (action == null) throw new NullPointerException();
- if (exhausted)
- return false;
- final ReentrantLock lock = LinkedBlockingDeque.this.lock;
- Node<E> p = current;
- E e = null;
- lock.lock();
- try {
- if ((p != null && p != p.next) || (p = first) != null) {
- e = p.item;
- p = p.next;
- }
- } finally {
- lock.unlock();
+ public void forEachRemaining(Consumer<? super E> action) {
+ Objects.requireNonNull(action);
+ if (!exhausted) {
+ exhausted = true;
+ Node<E> p = current;
+ current = null;
+ forEachFrom(action, p);
}
- exhausted = ((current = p) == null);
- if (e == null)
- return false;
- action.accept(e);
- return true;
}
public int characteristics() {
@@ -1251,6 +1273,48 @@
}
/**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void forEach(Consumer<? super E> action) {
+ Objects.requireNonNull(action);
+ forEachFrom(action, null);
+ }
+
+ /**
+ * Runs action on each element found during a traversal starting at p.
+ * If p is null, traversal starts at head.
+ */
+ void forEachFrom(Consumer<? super E> action, Node<E> p) {
+ // Extract batches of elements while holding the lock; then
+ // run the action on the elements while not
+ final ReentrantLock lock = this.lock;
+ final int batchSize = 32; // max number of elements per batch
+ Object[] es = null; // container for batch of elements
+ int n, len = 0;
+ do {
+ lock.lock();
+ try {
+ if (es == null) {
+ if (p == null) p = first;
+ for (Node<E> q = p; q != null; q = succ(q))
+ if (q.item != null && ++len == batchSize)
+ break;
+ es = new Object[len];
+ }
+ for (n = 0; p != null && n < len; p = succ(p))
+ if ((es[n] = p.item) != null)
+ n++;
+ } finally {
+ lock.unlock();
+ }
+ for (int i = 0; i < n; i++) {
+ @SuppressWarnings("unchecked") E e = (E) es[i];
+ action.accept(e);
+ }
+ } while (n > 0 && p != null);
+ }
+
+ /**
* Saves this deque to a stream (that is, serializes it).
*
* @param s the stream
@@ -1290,8 +1354,7 @@
last = null;
// Read in all elements and place in queue
for (;;) {
- @SuppressWarnings("unchecked")
- E item = (E)s.readObject();
+ @SuppressWarnings("unchecked") E item = (E)s.readObject();
if (item == null)
break;
add(item);
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java Thu Dec 22 18:48:53 2016 +0000
@@ -39,6 +39,7 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.concurrent.atomic.AtomicInteger;
@@ -234,14 +235,6 @@
putLock.unlock();
}
-// /**
-// * Tells whether both locks are held by current thread.
-// */
-// boolean isFullyLocked() {
-// return (putLock.isHeldByCurrentThread() &&
-// takeLock.isHeldByCurrentThread());
-// }
-
/**
* Creates a {@code LinkedBlockingQueue} with a capacity of
* {@link Integer#MAX_VALUE}.
@@ -517,7 +510,8 @@
* Unlinks interior Node p with predecessor trail.
*/
void unlink(Node<E> p, Node<E> trail) {
- // assert isFullyLocked();
+ // assert putLock.isHeldByCurrentThread();
+ // assert takeLock.isHeldByCurrentThread();
// p.next is not changed, to allow iterators that are
// traversing p to maintain their weak-consistency guarantee.
p.item = null;
@@ -701,8 +695,7 @@
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c, int maxElements) {
- if (c == null)
- throw new NullPointerException();
+ Objects.requireNonNull(c);
if (c == this)
throw new IllegalArgumentException();
if (maxElements <= 0)
@@ -741,6 +734,16 @@
}
/**
+ * Used for any element traversal that is not entirely under lock.
+ * Such traversals must handle both:
+ * - dequeued nodes (p.next == p)
+ * - (possibly multiple) interior removed nodes (p.item == null)
+ */
+ Node<E> succ(Node<E> p) {
+ return (p == (p = p.next)) ? head.next : p;
+ }
+
+ /**
* Returns an iterator over the elements in this queue in proper sequence.
* The elements will be returned in order from first (head) to last (tail).
*
@@ -760,48 +763,80 @@
* still have it to return even if lost race with a take etc.
*/
- private Node<E> current;
+ private Node<E> next;
+ private E nextItem;
private Node<E> lastRet;
- private E currentElement;
Itr() {
fullyLock();
try {
- current = head.next;
- if (current != null)
- currentElement = current.item;
+ if ((next = head.next) != null)
+ nextItem = next.item;
} finally {
fullyUnlock();
}
}
public boolean hasNext() {
- return current != null;
+ return next != null;
}
public E next() {
+ Node<E> p;
+ if ((p = next) == null)
+ throw new NoSuchElementException();
+ lastRet = p;
+ E x = nextItem;
fullyLock();
try {
- if (current == null)
- throw new NoSuchElementException();
- lastRet = current;
- E item = null;
- // Unlike other traversal methods, iterators must handle both:
- // - dequeued nodes (p.next == p)
- // - (possibly multiple) interior removed nodes (p.item == null)
- for (Node<E> p = current, q;; p = q) {
- if ((q = p.next) == p)
- q = head.next;
- if (q == null || (item = q.item) != null) {
- current = q;
- E x = currentElement;
- currentElement = item;
- return x;
- }
- }
+ E e = null;
+ for (p = p.next; p != null && (e = p.item) == null; )
+ p = succ(p);
+ next = p;
+ nextItem = e;
} finally {
fullyUnlock();
}
+ return x;
+ }
+
+ public void forEachRemaining(Consumer<? super E> action) {
+ // A variant of forEachFrom
+ Objects.requireNonNull(action);
+ Node<E> p;
+ if ((p = next) == null) return;
+ lastRet = p;
+ next = null;
+ final int batchSize = 32;
+ Object[] es = null;
+ int n, len = 1;
+ do {
+ fullyLock();
+ try {
+ if (es == null) {
+ p = p.next;
+ for (Node<E> q = p; q != null; q = succ(q))
+ if (q.item != null && ++len == batchSize)
+ break;
+ es = new Object[len];
+ es[0] = nextItem;
+ nextItem = null;
+ n = 1;
+ } else
+ n = 0;
+ for (; p != null && n < len; p = succ(p))
+ if ((es[n] = p.item) != null) {
+ lastRet = p;
+ n++;
+ }
+ } finally {
+ fullyUnlock();
+ }
+ for (int i = 0; i < n; i++) {
+ @SuppressWarnings("unchecked") E e = (E) es[i];
+ action.accept(e);
+ }
+ } while (n > 0 && p != null);
}
public void remove() {
@@ -825,42 +860,39 @@
}
}
- /** A customized variant of Spliterators.IteratorSpliterator */
- static final class LBQSpliterator<E> implements Spliterator<E> {
+ /**
+ * A customized variant of Spliterators.IteratorSpliterator.
+ * Keep this class in sync with (very similar) LBDSpliterator.
+ */
+ private final class LBQSpliterator implements Spliterator<E> {
static final int MAX_BATCH = 1 << 25; // max batch array size;
- final LinkedBlockingQueue<E> queue;
Node<E> current; // current node; null until initialized
int batch; // batch size for splits
boolean exhausted; // true when no more nodes
- long est; // size estimate
- LBQSpliterator(LinkedBlockingQueue<E> queue) {
- this.queue = queue;
- this.est = queue.size();
- }
+ long est = size(); // size estimate
+
+ LBQSpliterator() {}
public long estimateSize() { return est; }
public Spliterator<E> trySplit() {
Node<E> h;
- final LinkedBlockingQueue<E> q = this.queue;
int b = batch;
int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
if (!exhausted &&
- ((h = current) != null || (h = q.head.next) != null) &&
- h.next != null) {
+ ((h = current) != null || (h = head.next) != null)
+ && h.next != null) {
Object[] a = new Object[n];
int i = 0;
Node<E> p = current;
- q.fullyLock();
+ fullyLock();
try {
- if (p != null || (p = q.head.next) != null) {
- do {
+ if (p != null || (p = head.next) != null)
+ for (; p != null && i < n; p = succ(p))
if ((a[i] = p.item) != null)
- ++i;
- } while ((p = p.next) != null && i < n);
- }
+ i++;
} finally {
- q.fullyUnlock();
+ fullyUnlock();
}
if ((current = p) == null) {
est = 0L;
@@ -879,53 +911,22 @@
return null;
}
- public void forEachRemaining(Consumer<? super E> action) {
- if (action == null) throw new NullPointerException();
- final LinkedBlockingQueue<E> q = this.queue;
- if (!exhausted) {
- exhausted = true;
- Node<E> p = current;
- do {
- E e = null;
- q.fullyLock();
- try {
- if (p == null)
- p = q.head.next;
- while (p != null) {
- e = p.item;
- p = p.next;
- if (e != null)
- break;
- }
- } finally {
- q.fullyUnlock();
- }
- if (e != null)
- action.accept(e);
- } while (p != null);
- }
- }
-
public boolean tryAdvance(Consumer<? super E> action) {
- if (action == null) throw new NullPointerException();
- final LinkedBlockingQueue<E> q = this.queue;
+ Objects.requireNonNull(action);
if (!exhausted) {
E e = null;
- q.fullyLock();
+ fullyLock();
try {
- if (current == null)
- current = q.head.next;
- while (current != null) {
- e = current.item;
- current = current.next;
- if (e != null)
- break;
- }
+ Node<E> p;
+ if ((p = current) != null || (p = head.next) != null)
+ do {
+ e = p.item;
+ p = succ(p);
+ } while (e == null && p != null);
+ exhausted = ((current = p) == null);
} finally {
- q.fullyUnlock();
+ fullyUnlock();
}
- if (current == null)
- exhausted = true;
if (e != null) {
action.accept(e);
return true;
@@ -934,9 +935,20 @@
return false;
}
+ public void forEachRemaining(Consumer<? super E> action) {
+ Objects.requireNonNull(action);
+ if (!exhausted) {
+ exhausted = true;
+ Node<E> p = current;
+ current = null;
+ forEachFrom(action, p);
+ }
+ }
+
public int characteristics() {
- return Spliterator.ORDERED | Spliterator.NONNULL |
- Spliterator.CONCURRENT;
+ return (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT);
}
}
@@ -957,7 +969,48 @@
* @since 1.8
*/
public Spliterator<E> spliterator() {
- return new LBQSpliterator<E>(this);
+ return new LBQSpliterator();
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void forEach(Consumer<? super E> action) {
+ Objects.requireNonNull(action);
+ forEachFrom(action, null);
+ }
+
+ /**
+ * Runs action on each element found during a traversal starting at p.
+ * If p is null, traversal starts at head.
+ */
+ void forEachFrom(Consumer<? super E> action, Node<E> p) {
+ // Extract batches of elements while holding the lock; then
+ // run the action on the elements while not
+ final int batchSize = 32; // max number of elements per batch
+ Object[] es = null; // container for batch of elements
+ int n, len = 0;
+ do {
+ fullyLock();
+ try {
+ if (es == null) {
+ if (p == null) p = head.next;
+ for (Node<E> q = p; q != null; q = succ(q))
+ if (q.item != null && ++len == batchSize)
+ break;
+ es = new Object[len];
+ }
+ for (n = 0; p != null && n < len; p = succ(p))
+ if ((es[n] = p.item) != null)
+ n++;
+ } finally {
+ fullyUnlock();
+ }
+ for (int i = 0; i < n; i++) {
+ @SuppressWarnings("unchecked") E e = (E) es[i];
+ action.accept(e);
+ }
+ } while (n > 0 && p != null);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java Thu Dec 22 18:48:53 2016 +0000
@@ -179,7 +179,7 @@
* void startTasks(List<Runnable> tasks, int iterations) {
* Phaser phaser = new Phaser() {
* protected boolean onAdvance(int phase, int registeredParties) {
- * return phase >= iterations || registeredParties == 0;
+ * return phase >= iterations - 1 || registeredParties == 0;
* }
* };
* phaser.register();
--- a/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java Thu Dec 22 18:48:53 2016 +0000
@@ -345,11 +345,9 @@
* promoting x up the tree until it is greater than or equal to
* its parent, or is the root.
*
- * To simplify and speed up coercions and comparisons. the
+ * To simplify and speed up coercions and comparisons, the
* Comparable and Comparator versions are separated into different
* methods that are otherwise identical. (Similarly for siftDown.)
- * These methods are static, with heap state as arguments, to
- * simplify use in light of possible comparator exceptions.
*
* @param k the position to fill
* @param x the item to insert
@@ -435,6 +433,7 @@
/**
* Establishes the heap invariant (described above) in the entire tree,
* assuming nothing about the order of the elements prior to the call.
+ * This classic algorithm due to Floyd (1964) is known to be O(size).
*/
private void heapify() {
Object[] array = queue;
@@ -878,8 +877,7 @@
public E next() {
if (cursor >= array.length)
throw new NoSuchElementException();
- lastRet = cursor;
- return (E)array[cursor++];
+ return (E)array[lastRet = cursor++];
}
public void remove() {
@@ -936,15 +934,12 @@
/**
* Immutable snapshot spliterator that binds to elements "late".
*/
- static final class PBQSpliterator<E> implements Spliterator<E> {
- final PriorityBlockingQueue<E> queue;
+ final class PBQSpliterator implements Spliterator<E> {
Object[] array;
int index;
int fence;
- PBQSpliterator(PriorityBlockingQueue<E> queue, Object[] array,
- int index, int fence) {
- this.queue = queue;
+ PBQSpliterator(Object[] array, int index, int fence) {
this.array = array;
this.index = index;
this.fence = fence;
@@ -953,14 +948,14 @@
final int getFence() {
int hi;
if ((hi = fence) < 0)
- hi = fence = (array = queue.toArray()).length;
+ hi = fence = (array = toArray()).length;
return hi;
}
- public PBQSpliterator<E> trySplit() {
+ public PBQSpliterator trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid) ? null :
- new PBQSpliterator<E>(queue, array, lo, index = mid);
+ new PBQSpliterator(array, lo, index = mid);
}
@SuppressWarnings("unchecked")
@@ -969,7 +964,7 @@
if (action == null)
throw new NullPointerException();
if ((a = array) == null)
- fence = (a = queue.toArray()).length;
+ fence = (a = toArray()).length;
if ((hi = fence) <= a.length &&
(i = index) >= 0 && i < (index = hi)) {
do { action.accept((E)a[i]); } while (++i < hi);
@@ -987,7 +982,7 @@
return false;
}
- public long estimateSize() { return (long)(getFence() - index); }
+ public long estimateSize() { return getFence() - index; }
public int characteristics() {
return Spliterator.NONNULL | Spliterator.SIZED | Spliterator.SUBSIZED;
@@ -1012,7 +1007,7 @@
* @since 1.8
*/
public Spliterator<E> spliterator() {
- return new PBQSpliterator<E>(this, null, 0, -1);
+ return new PBQSpliterator(null, 0, -1);
}
// VarHandle mechanics
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Thu Dec 22 18:48:53 2016 +0000
@@ -1306,8 +1306,7 @@
public Runnable next() {
if (cursor >= array.length)
throw new NoSuchElementException();
- lastRet = cursor;
- return array[cursor++];
+ return array[lastRet = cursor++];
}
public void remove() {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java Thu Dec 22 18:48:53 2016 +0000
@@ -195,6 +195,7 @@
/** Fallback if ForkJoinPool.commonPool() cannot support parallelism */
private static final class ThreadPerTaskExecutor implements Executor {
+ ThreadPerTaskExecutor() {} // prevent access constructor creation
public void execute(Runnable r) { new Thread(r).start(); }
}
@@ -1454,7 +1455,17 @@
*/
private boolean checkControl(Flow.Subscriber<? super T> s, int c) {
boolean stat = true;
- if ((c & ERROR) != 0) {
+ if ((c & SUBSCRIBE) != 0) {
+ if (CTL.compareAndSet(this, c, c & ~SUBSCRIBE)) {
+ try {
+ if (s != null)
+ s.onSubscribe(this);
+ } catch (Throwable ex) {
+ onError(ex);
+ }
+ }
+ }
+ else if ((c & ERROR) != 0) {
Throwable ex = pendingError;
ctl = DISABLED; // no need for CAS
if (ex != null) { // null if errorless cancel
@@ -1465,16 +1476,6 @@
}
}
}
- else if ((c & SUBSCRIBE) != 0) {
- if (CTL.compareAndSet(this, c, c & ~SUBSCRIBE)) {
- try {
- if (s != null)
- s.onSubscribe(this);
- } catch (Throwable ex) {
- onError(ex);
- }
- }
- }
else {
detach();
stat = false;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java Thu Dec 22 18:48:53 2016 +0000
@@ -138,7 +138,7 @@
* <pre> {@code
* class CachedData {
* Object data;
- * volatile boolean cacheValid;
+ * boolean cacheValid;
* final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
*
* void processCachedData() {
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java Thu Dec 22 18:48:53 2016 +0000
@@ -1338,7 +1338,7 @@
/**
* Registers a callback function that selects an application protocol
* value for a SSL/TLS/DTLS handshake.
- * The function overrides any values set using
+ * The function overrides any values supplied using
* {@link SSLParameters#setApplicationProtocols
* SSLParameters.setApplicationProtocols} and it supports the following
* type parameters:
@@ -1354,6 +1354,8 @@
* <dt> {@code String}
* <dd> The function's result is an application protocol name, or null to
* indicate that none of the advertised names are acceptable.
+ * If the return value is an empty {@code String} then application
+ * protocol indications will not be used.
* If the return value is null (no value chosen) or is a value that
* was not advertised by the peer, the underlying protocol will
* determine what action to take. (For example, ALPN will send a
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocket.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocket.java Thu Dec 22 18:48:53 2016 +0000
@@ -749,7 +749,7 @@
/**
* Registers a callback function that selects an application protocol
* value for a SSL/TLS/DTLS handshake.
- * The function overrides any values set using
+ * The function overrides any values supplied using
* {@link SSLParameters#setApplicationProtocols
* SSLParameters.setApplicationProtocols} and it supports the following
* type parameters:
@@ -765,6 +765,8 @@
* <dt> {@code String}
* <dd> The function's result is an application protocol name, or null to
* indicate that none of the advertised names are acceptable.
+ * If the return value is an empty {@code String} then application
+ * protocol indications will not be used.
* If the return value is null (no value chosen) or is a value that
* was not advertised by the peer, the underlying protocol will
* determine what action to take. (For example, ALPN will send a
--- a/jdk/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java Thu Dec 22 18:48:53 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -31,7 +31,7 @@
import java.nio.channels.*;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
-
+import java.util.concurrent.TimeUnit;
// Make a socket channel look like a socket.
//
@@ -99,17 +99,19 @@
try {
if (sc.connect(remote))
return;
- long to = timeout;
+ long timeoutNanos =
+ TimeUnit.NANOSECONDS.convert(timeout,
+ TimeUnit.MILLISECONDS);
for (;;) {
if (!sc.isOpen())
throw new ClosedChannelException();
- long st = System.currentTimeMillis();
+ long startTime = System.nanoTime();
- int result = sc.poll(Net.POLLCONN, to);
+ int result = sc.poll(Net.POLLCONN, timeout);
if (result > 0 && sc.finishConnect())
break;
- to -= System.currentTimeMillis() - st;
- if (to <= 0) {
+ timeoutNanos -= System.nanoTime() - startTime;
+ if (timeoutNanos <= 0) {
try {
sc.close();
} catch (IOException x) { }
@@ -194,18 +196,20 @@
int n;
if ((n = sc.read(bb)) != 0)
return n;
- long to = timeout;
+ long timeoutNanos =
+ TimeUnit.NANOSECONDS.convert(timeout,
+ TimeUnit.MILLISECONDS);
for (;;) {
if (!sc.isOpen())
throw new ClosedChannelException();
- long st = System.currentTimeMillis();
- int result = sc.poll(Net.POLLIN, to);
+ long startTime = System.nanoTime();
+ int result = sc.poll(Net.POLLIN, timeout);
if (result > 0) {
if ((n = sc.read(bb)) != 0)
return n;
}
- to -= System.currentTimeMillis() - st;
- if (to <= 0)
+ timeoutNanos -= System.nanoTime() - startTime;
+ if (timeoutNanos <= 0)
throw new SocketTimeoutException();
}
} finally {
--- a/jdk/src/java.base/share/classes/sun/security/provider/CtrDrbg.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/provider/CtrDrbg.java Thu Dec 22 18:48:53 2016 +0000
@@ -80,7 +80,7 @@
@Override
protected void chooseAlgorithmAndStrength() {
if (requestedAlgorithm != null) {
- algorithm = requestedAlgorithm.toUpperCase();
+ algorithm = requestedAlgorithm.toUpperCase(Locale.ROOT);
int supportedStrength = alg2strength(algorithm);
if (requestedInstantiationSecurityStrength >= 0) {
int tryStrength = getStandardStrength(
--- a/jdk/src/java.base/share/classes/sun/security/x509/AlgorithmId.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/x509/AlgorithmId.java Thu Dec 22 18:48:53 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -1009,7 +1009,7 @@
* @return the default alg, might be null if unsupported
*/
public static String getDefaultSigAlgForKey(PrivateKey k) {
- switch (k.getAlgorithm().toUpperCase()) {
+ switch (k.getAlgorithm().toUpperCase(Locale.ROOT)) {
case "EC":
return ecStrength(KeyUtil.getKeySize(k))
+ "withECDSA";
--- a/jdk/src/java.desktop/share/classes/java/beans/PropertyDescriptor.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/java/beans/PropertyDescriptor.java Thu Dec 22 18:48:53 2016 +0000
@@ -183,9 +183,10 @@
setShortDescription(description.toString());
}
Object values = info.get(PropertyInfo.Name.enumerationValues);
- if (values != null) {
- setValue(PropertyInfo.Name.enumerationValues.name(), values);
+ if (values == null) {
+ values = new Object[0];
}
+ setValue(PropertyInfo.Name.enumerationValues.name(), values);
this.baseName = base;
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/JToggleButton.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JToggleButton.java Thu Dec 22 18:48:53 2016 +0000
@@ -34,6 +34,7 @@
import java.io.ObjectOutputStream;
import java.io.IOException;
+import java.util.Iterator;
/**
* An implementation of a two-state button.
@@ -208,6 +209,96 @@
return true;
}
+ private JToggleButton getGroupSelection(FocusEvent.Cause cause) {
+ switch (cause) {
+ case ACTIVATION:
+ case TRAVERSAL:
+ case TRAVERSAL_UP:
+ case TRAVERSAL_DOWN:
+ case TRAVERSAL_FORWARD:
+ case TRAVERSAL_BACKWARD:
+ ButtonModel model = getModel();
+ JToggleButton selection = this;
+ if (model instanceof DefaultButtonModel) {
+ ButtonGroup group = ((DefaultButtonModel) model).getGroup();
+ if (group != null && group.getSelection() != null
+ && !group.isSelected(model)) {
+ Iterator<AbstractButton> iterator =
+ group.getElements().asIterator();
+ while (iterator.hasNext()) {
+ AbstractButton member = iterator.next();
+ if (group.isSelected(member.getModel())) {
+ if (member instanceof JToggleButton &&
+ member.isVisible() && member.isDisplayable() &&
+ member.isEnabled() && member.isFocusable()) {
+ selection = (JToggleButton) member;
+ }
+ break;
+ }
+ }
+ }
+ }
+ return selection;
+ default:
+ return this;
+ }
+ }
+
+ /**
+ * If this toggle button is a member of the {@link ButtonGroup} which has
+ * another toggle button which is selected and can be the focus owner,
+ * and the focus cause argument denotes window activation or focus
+ * traversal action of any direction the result of the method execution
+ * is the same as calling
+ * {@link Component#requestFocus(FocusEvent.Cause)} on the toggle button
+ * selected in the group.
+ * In all other cases the result of the method is the same as calling
+ * {@link Component#requestFocus(FocusEvent.Cause)} on this toggle button.
+ *
+ * @param cause the cause why the focus is requested
+ * @see ButtonGroup
+ * @see Component#requestFocus(FocusEvent.Cause)
+ * @see FocusEvent.Cause
+ *
+ * @since 9
+ */
+ @Override
+ public void requestFocus(FocusEvent.Cause cause) {
+ getGroupSelection(cause).requestFocusUnconditionally(cause);
+ }
+
+ private void requestFocusUnconditionally(FocusEvent.Cause cause) {
+ super.requestFocus(cause);
+ }
+
+ /**
+ * If this toggle button is a member of the {@link ButtonGroup} which has
+ * another toggle button which is selected and can be the focus owner,
+ * and the focus cause argument denotes window activation or focus
+ * traversal action of any direction the result of the method execution
+ * is the same as calling
+ * {@link Component#requestFocusInWindow(FocusEvent.Cause)} on the toggle
+ * button selected in the group.
+ * In all other cases the result of the method is the same as calling
+ * {@link Component#requestFocusInWindow(FocusEvent.Cause)} on this toggle
+ * button.
+ *
+ * @param cause the cause why the focus is requested
+ * @see ButtonGroup
+ * @see Component#requestFocusInWindow(FocusEvent.Cause)
+ * @see FocusEvent.Cause
+ *
+ * @since 9
+ */
+ public boolean requestFocusInWindow(FocusEvent.Cause cause) {
+ return getGroupSelection(cause)
+ .requestFocusInWindowUnconditionally(cause);
+ }
+
+ private boolean requestFocusInWindowUnconditionally(FocusEvent.Cause cause) {
+ return super.requestFocusInWindow(cause);
+ }
+
// *********************************************************************
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/UIManager.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/UIManager.java Thu Dec 22 18:48:53 2016 +0000
@@ -629,16 +629,7 @@
}
else {
Class<?> lnfClass = SwingUtilities.loadSystemClass(className);
- try {
- LookAndFeel laf =
- (LookAndFeel)lnfClass.newInstance();
- setLookAndFeel(laf);
- } catch (ReflectiveOperationException | IllegalArgumentException e) {
- InstantiationException ex =
- new InstantiationException("Wrapped Exception");
- ex.initCause(e);
- throw ex;
- }
+ setLookAndFeel((LookAndFeel)(lnfClass.newInstance()));
}
}
--- a/jdk/src/java.desktop/share/classes/sun/awt/FontConfiguration.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/sun/awt/FontConfiguration.java Thu Dec 22 18:48:53 2016 +0000
@@ -182,11 +182,17 @@
throw new Error("java.home property not set");
}
javaLib = javaHome + File.separator + "lib";
+ String javaConfFonts = javaHome +
+ File.separator + "conf" +
+ File.separator + "fonts";
String userConfigFile = System.getProperty("sun.awt.fontconfig");
if (userConfigFile != null) {
fontConfigFile = new File(userConfigFile);
} else {
- fontConfigFile = findFontConfigFile(javaLib);
+ fontConfigFile = findFontConfigFile(javaConfFonts);
+ if (fontConfigFile == null) {
+ fontConfigFile = findFontConfigFile(javaLib);
+ }
}
}
@@ -275,8 +281,11 @@
return null;
}
- private File findFontConfigFile(String javaLib) {
- String baseName = javaLib + File.separator + "fontconfig";
+ private File findFontConfigFile(String dir) {
+ if (!(new File(dir)).exists()) {
+ return null;
+ }
+ String baseName = dir + File.separator + "fontconfig";
File configFile;
String osMajorVersion = null;
if (osVersion != null && osName != null) {
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/ScriptAndLanguageTags.cpp Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/ScriptAndLanguageTags.cpp Thu Dec 22 18:48:53 2016 +0000
@@ -33,13 +33,14 @@
* Generated on: 10/26/2010 02:53:33 PM PDT
*/
+#include "LEScripts.h"
#include "LETypes.h"
#include "ScriptAndLanguageTags.h"
#include "OpenTypeLayoutEngine.h"
U_NAMESPACE_BEGIN
-const LETag OpenTypeLayoutEngine::scriptTags[] = {
+const LETag OpenTypeLayoutEngine::scriptTags[scriptCodeCount] = {
zyyyScriptTag, /* 'zyyy' (COMMON) */
zinhScriptTag, /* 'zinh' (INHERITED) */
arabScriptTag, /* 'arab' (ARABIC) */
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/ThaiShaping.cpp Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/ThaiShaping.cpp Thu Dec 22 18:48:53 2016 +0000
@@ -302,7 +302,7 @@
le_uint8 charClass;
// Decompose SARA AM into NIKHAHIT + SARA AA
- if (ch == CH_SARA_AM && isLegalHere(ch, state)) {
+ if (ch == CH_SARA_AM && isLegalHere(ch, state) && conState < stateCount) {
outputIndex = conOutput;
state = getNextState(CH_NIKHAHIT, conState, inputIndex, glyphSet, errorChar, charClass,
output, glyphStorage, outputIndex);
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/ThaiShaping.h Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/ThaiShaping.h Thu Dec 22 18:48:53 2016 +0000
@@ -80,7 +80,8 @@
tG = 5,
tH = 6,
tR = 7,
- tS = 8
+ tS = 8,
+ stateCount = 52
};
struct StateTransition
@@ -100,7 +101,7 @@
ThaiShaping();
static const le_uint8 classTable[];
- static const StateTransition thaiStateTable[][classCount];
+ static const StateTransition thaiStateTable[stateCount][classCount];
inline static StateTransition getTransition(le_uint8 state, le_uint8 currClass);
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/ThaiStateTables.cpp Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/ThaiStateTables.cpp Thu Dec 22 18:48:53 2016 +0000
@@ -49,7 +49,7 @@
/*0E50*/ NON, NON, NON, NON, NON, NON, NON, NON, NON, NON, NON, NON
};
-const ThaiShaping::StateTransition ThaiShaping::thaiStateTable[][ThaiShaping::classCount] = {
+const ThaiShaping::StateTransition ThaiShaping::thaiStateTable[ThaiShaping::stateCount][ThaiShaping::classCount] = {
//+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| N C C C L F F F B B B T A A A N A A A |
//| O O O O V V V V V V D O D D D I V V V |
--- a/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_Ports.c Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_Ports.c Thu Dec 22 18:48:53 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, 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
@@ -385,6 +385,7 @@
int isStereo;
char* type;
snd_mixer_selem_channel_id_t channel;
+ memset(controls, 0, sizeof(controls));
TRACE0("> PORT_GetControls\n");
if (id == NULL) {
--- a/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_Ports.c Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_Ports.c Thu Dec 22 18:48:53 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, 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
@@ -385,6 +385,7 @@
int isStereo;
char* type;
snd_mixer_selem_channel_id_t channel;
+ memset(controls, 0, sizeof(controls));
TRACE0("> PORT_GetControls\n");
if (id == NULL) {
--- a/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_SolarisOS_Ports.c Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_SolarisOS_Ports.c Thu Dec 22 18:48:53 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2007, 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
@@ -390,6 +390,7 @@
int controlCount = 0;
INT32 type;
int selectable = 1;
+ memset(controls, 0, sizeof(controls));
TRACE4(">PORT_GetControls(id=%p, portIndex=%d). controlIDs=%p, maxControlCount=%d\n",
id, portIndex, info->controlIDs, info->maxControlCount);
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipherWithJavaPadding.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipherWithJavaPadding.java Thu Dec 22 18:48:53 2016 +0000
@@ -28,6 +28,7 @@
import java.nio.ByteBuffer;
import java.util.Set;
import java.util.Arrays;
+import java.util.Locale;
import java.util.concurrent.ConcurrentSkipListSet;
import java.lang.ref.*;
@@ -262,7 +263,7 @@
throws NoSuchAlgorithmException, NoSuchPaddingException {
this.nc = nc;
this.blockSize = nc.engineGetBlockSize();
- if (paddingScheme.toUpperCase().equals("PKCS5PADDING")) {
+ if (paddingScheme.toUpperCase(Locale.ROOT).equals("PKCS5PADDING")) {
padding = new PKCS5Padding(blockSize);
} else {
throw new NoSuchAlgorithmException("Unsupported padding scheme: " + paddingScheme);
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java Thu Dec 22 18:48:53 2016 +0000
@@ -74,6 +74,7 @@
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.Set;
+import java.util.TreeSet;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -497,6 +498,7 @@
// Add (or replace) the Packages attribute
if (packages != null) {
+ validatePackages(descriptor, packages);
extender.packages(packages);
}
@@ -530,6 +532,24 @@
}
}
+ private void validatePackages(ModuleDescriptor descriptor, Set<String> packages) {
+ Set<String> nonExistPackages = new TreeSet<>();
+ descriptor.exports().stream()
+ .map(Exports::source)
+ .filter(pn -> !packages.contains(pn))
+ .forEach(nonExistPackages::add);
+
+ descriptor.opens().stream()
+ .map(Opens::source)
+ .filter(pn -> !packages.contains(pn))
+ .forEach(nonExistPackages::add);
+
+ if (!nonExistPackages.isEmpty()) {
+ throw new CommandException("err.missing.export.or.open.packages",
+ descriptor.name(), nonExistPackages);
+ }
+ }
+
/*
* Hasher resolves a module graph using the --hash-modules PATTERN
* as the roots.
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties Thu Dec 22 18:48:53 2016 +0000
@@ -107,6 +107,7 @@
err.internal.error=internal error: {0} {1} {2}
err.invalid.dryrun.option=--dry-run can only be used with hash mode
err.module.descriptor.not.found=Module descriptor not found
+err.missing.export.or.open.packages=Packages that are exported or open in {0} are not present: {1}
warn.invalid.arg=Invalid classname or pathname not exist: {0}
warn.no.module.hashes=No hashes recorded: no module specified for hashing depends on {0}
warn.module.resolution.fail=No hashes recorded: {0}
--- a/jdk/test/ProblemList.txt Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/ProblemList.txt Thu Dec 22 18:48:53 2016 +0000
@@ -203,8 +203,6 @@
sun/rmi/rmic/newrmic/equivalence/run.sh 8145980 generic-all
-java/rmi/transport/dgcDeadLock/DGCDeadLock.java 8029360 macosx-all
-
java/rmi/registry/readTest/readTest.sh 7146543 generic-all
############################################################################
@@ -217,10 +215,6 @@
sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java 8026393 generic-all
-sun/security/ssl/SSLSocketImpl/AsyncSSLSocketClose.java 8161232 macosx-all
-
-sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java 8171043 windows-all
-
javax/net/ssl/DTLS/PacketLossRetransmission.java 8169086 macosx-x64
############################################################################
@@ -234,8 +228,6 @@
javax/sound/sampled/Mixers/DisabledAssertionCrash.java 7067310 generic-all
-javax/sound/sampled/Clip/OpenNonIntegralNumberOfSampleframes.java 8168881 generic-all
-
############################################################################
# jdk_imageio
--- a/jdk/test/java/awt/EmbeddedFrame/DisplayChangedTest/DisplayChangedTest.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/java/awt/EmbeddedFrame/DisplayChangedTest/DisplayChangedTest.java Thu Dec 22 18:48:53 2016 +0000
@@ -23,12 +23,12 @@
/*
@test
- @bug 4980592
+ @bug 4980592 8171363
@summary switching user in XP causes an NPE in
sun.awt.windows.WWindowPeer.displayChanged
@requires (os.family == "windows")
@modules java.desktop/java.awt.peer
- @modules java.desktop/sun.awt.windows
+ @modules java.desktop/sun.awt.windows:open
@modules java.desktop/sun.awt
@author son@sparc.spb.su: area=embedded
@run main DisplayChangedTest
--- a/jdk/test/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java Thu Dec 22 18:48:53 2016 +0000
@@ -23,12 +23,12 @@
/*
@test
- @bug 6345002
+ @bug 6345003 8171363
@summary grab problems with EmbeddedFrame
@requires (os.family == "windows")
@modules java.desktop/java.awt.peer
@modules java.desktop/sun.awt
- @modules java.desktop/sun.awt.windows
+ @modules java.desktop/sun.awt.windows:open
@author Oleg.Semenov@sun.com area=EmbeddedFrame
@run main EmbeddedFrameGrabTest
*/
--- a/jdk/test/java/awt/datatransfer/ConstructFlavoredObjectTest/ConstructFlavoredObjectTest.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/java/awt/datatransfer/ConstructFlavoredObjectTest/ConstructFlavoredObjectTest.java Thu Dec 22 18:48:53 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -31,34 +31,57 @@
/*
* @test
* @key headful
- * @bug 8130329
+ * @bug 8130329 8134612 8133719
* @summary Audit Core Reflection in module java.desktop AWT/Miscellaneous area
* for places that will require changes to work with modules
* @author Alexander Scherbatiy
+ * @run main/othervm ConstructFlavoredObjectTest COPY
+ * @run main/othervm ConstructFlavoredObjectTest PASTE
*/
public class ConstructFlavoredObjectTest {
- private static final String TEST_MIME_TYPE = "text/plain;class="
- + MyStringReader.class.getName();
-
public static void main(String[] args) throws Exception {
- final DataFlavor dataFlavor = new DataFlavor(TEST_MIME_TYPE);
- SystemFlavorMap systemFlavorMap = (SystemFlavorMap) SystemFlavorMap.
- getDefaultFlavorMap();
- systemFlavorMap.addUnencodedNativeForFlavor(dataFlavor, "TEXT");
- systemFlavorMap.addFlavorForUnencodedNative("TEXT", dataFlavor);
+ if (args[0].equals("COPY")) {
+
+ // Copy a simple text string on to the System clipboard
+
+ final String TEXT_MIME_TYPE = DataFlavor.javaJVMLocalObjectMimeType +
+ ";class=" + String.class.getName();
- TransferHandler transferHandler = new TransferHandler("Test Handler");
+ final DataFlavor dataFlavor = new DataFlavor(TEXT_MIME_TYPE);
+ SystemFlavorMap systemFlavorMap =
+ (SystemFlavorMap) SystemFlavorMap.getDefaultFlavorMap();
+ systemFlavorMap.addUnencodedNativeForFlavor(dataFlavor, "TEXT");
+ systemFlavorMap.addFlavorForUnencodedNative("TEXT", dataFlavor);
+
+ TransferHandler transferHandler = new TransferHandler("text");
- Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
- transferHandler.exportToClipboard(new JLabel("Test"), clipboard,
- TransferHandler.COPY);
+ String text = "This is sample export text";
+ Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+ transferHandler.exportToClipboard(new JLabel(text), clipboard,
+ TransferHandler.COPY);
+ }
+ else if (args[0].equals("PASTE")) {
+
+ // Try to read text data from the System clipboard
+
+ final String TEST_MIME_TYPE = "text/plain;class=" +
+ MyStringReader.class.getName();
- Object clipboardData = clipboard.getData(dataFlavor);
+ final DataFlavor dataFlavor = new DataFlavor(TEST_MIME_TYPE);
+ SystemFlavorMap systemFlavorMap = (SystemFlavorMap) SystemFlavorMap.
+ getDefaultFlavorMap();
+ systemFlavorMap.addUnencodedNativeForFlavor(dataFlavor, "TEXT");
+ systemFlavorMap.addFlavorForUnencodedNative("TEXT", dataFlavor);
- if (!(clipboardData instanceof MyStringReader)) {
- throw new RuntimeException("Wrong clipboard data!");
+ Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+
+ Object clipboardData = clipboard.getData(dataFlavor);
+
+ if (!(clipboardData instanceof MyStringReader)) {
+ throw new RuntimeException("Wrong clipboard data!");
+ }
}
}
@@ -78,3 +101,4 @@
}
}
}
+
--- a/jdk/test/java/beans/Introspector/8130937/TestBooleanBeanProperties.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/java/beans/Introspector/8130937/TestBooleanBeanProperties.java Thu Dec 22 18:48:53 2016 +0000
@@ -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
@@ -28,7 +28,7 @@
/**
* @test
- * @bug 8130937
+ * @bug 8130937 8131347
* @summary Tests the booleans properties of the BeanProperty annotation
* @library ..
*/
@@ -76,6 +76,9 @@
if (getValue(pd, "visualUpdate") != isVS) {
throw new RuntimeException("required should be: " + isVS);
}
+ if (pd.getValue("enumerationValues") == null) {
+ throw new RuntimeException("enumerationValues should be empty array");
+ }
}
private static boolean getValue(PropertyDescriptor pd, String value) {
@@ -107,7 +110,8 @@
}
@BeanProperty(bound = true, expert = true, hidden = true,
- preferred = true, required = true, visualUpdate = true)
+ preferred = true, required = true, visualUpdate = true,
+ enumerationValues = {})
public void setValue(int value) {
this.value = value;
}
--- a/jdk/test/java/rmi/testlibrary/REGISTRY.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/java/rmi/testlibrary/REGISTRY.java Thu Dec 22 18:48:53 2016 +0000
@@ -33,28 +33,48 @@
*/
public class REGISTRY extends JavaVM {
- private static double startTimeout = 20_000 * TestLibrary.getTimeoutFactor();
+ private static final double START_TIMEOUT =
+ 20_000 * TestLibrary.getTimeoutFactor();
+ private static final String DEFAULT_RUNNER = "RegistryRunner";
private int port = -1;
- private REGISTRY(OutputStream out, OutputStream err,
+ private REGISTRY(String runner, OutputStream out, OutputStream err,
String options, int port) {
- super("RegistryRunner", options, Integer.toString(port), out, err);
+ super(runner, options, Integer.toString(port), out, err);
+ try {
+ Class runnerClass = Class.forName(runner);
+ if (!RegistryRunner.class.isAssignableFrom(runnerClass)) {
+ throw new RuntimeException("runner class must be RegistryRunner"
+ + " or its sub class");
+ }
+ } catch (ClassNotFoundException ex) {
+ throw new RuntimeException(ex);
+ }
this.port = port;
}
public static REGISTRY createREGISTRY() {
- return createREGISTRY(System.out, System.err, "", 0);
+ return createREGISTRYWithRunner(DEFAULT_RUNNER, System.out, System.err, "", 0);
}
public static REGISTRY createREGISTRY(OutputStream out, OutputStream err,
String options, int port) {
+ return createREGISTRYWithRunner(DEFAULT_RUNNER, out, err, options, port);
+ }
+
+ public static REGISTRY createREGISTRYWithRunner(String runner, String options) {
+ return createREGISTRYWithRunner(runner, System.out, System.err, options, 0);
+ }
+
+ public static REGISTRY createREGISTRYWithRunner(String runner, OutputStream out,
+ OutputStream err, String options, int port) {
options += " --add-exports=java.rmi/sun.rmi.registry=ALL-UNNAMED"
- + " --add-exports=java.rmi/sun.rmi.server=ALL-UNNAMED"
- + " --add-exports=java.rmi/sun.rmi.transport=ALL-UNNAMED"
- + " --add-exports=java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED";
- REGISTRY reg = new REGISTRY(out, err, options, port);
- return reg;
+ + " --add-exports=java.rmi/sun.rmi.server=ALL-UNNAMED"
+ + " --add-exports=java.rmi/sun.rmi.transport=ALL-UNNAMED"
+ + " --add-exports=java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED";
+ REGISTRY reg = new REGISTRY(runner, out, err, options, port);
+ return reg;
}
/**
@@ -65,7 +85,7 @@
public void start() throws IOException {
super.start();
long startTime = System.currentTimeMillis();
- long deadline = TestLibrary.computeDeadline(startTime, (long)startTimeout);
+ long deadline = TestLibrary.computeDeadline(startTime, (long)START_TIMEOUT);
while (true) {
try {
Thread.sleep(1000);
--- a/jdk/test/java/rmi/testlibrary/RegistryRunner.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/java/rmi/testlibrary/RegistryRunner.java Thu Dec 22 18:48:53 2016 +0000
@@ -36,7 +36,7 @@
implements RemoteExiter
{
private static final String PORT_LABEL_START = "RegistryRunner.port.start:";
- private static final String PORT_LABEL_END = "RegistryRunner.port.end";
+ private static final String PORT_LABEL_END = ":RegistryRunner.port.end";
private static Registry registry = null;
private static RemoteExiter exiter = null;
@@ -95,17 +95,17 @@
return port;
}
- public static void main(String[] args) {
-
+ /**
+ * port 0 means to use ephemeral port to start registry.
+ */
+ protected static int init(String[] args) {
try {
if (args.length == 0) {
System.err.println("Usage: <port>");
System.exit(0);
}
int port = -1;
- try {
- port = Integer.parseInt(args[0]);
- } catch (NumberFormatException ignore) { }
+ port = Integer.parseInt(args[0]);
// create a registry
registry = LocateRegistry.createRegistry(port);
@@ -118,14 +118,30 @@
Naming.rebind("rmi://localhost:" + port +
"/RemoteExiter", exiter);
- // this output is important for REGISTRY to get the port
- // where rmiregistry is serving
- System.out.println(PORT_LABEL_START + port + PORT_LABEL_END);
-
+ return port;
} catch (Exception e) {
System.err.println(e.getMessage());
e.printStackTrace();
System.exit(-1);
}
+ return -1;
+ }
+
+ /**
+ * REGISTRY.start() will filter the output of registry subprocess,
+ * when valid port is detected, REGISTRY.start() returns.
+ * So, for subclass, it's important to call this method after registry
+ * is initialized and necessary remote objects have been bound.
+ */
+ protected static void notify(int port) {
+ // this output is important for REGISTRY to get the port
+ // where rmiregistry is serving
+ System.out.println(PORT_LABEL_START + port + PORT_LABEL_END);
+ System.out.flush();
+ }
+
+ public static void main(String[] args) {
+ int port = init(args);
+ notify(port);
}
}
--- a/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java Thu Dec 22 18:48:53 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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,7 +33,7 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary Test TestImpl TestImpl_Stub
+ * @build TestLibrary Test TestImpl REGISTRY RegistryRunner
* @run main/othervm/policy=security.policy/timeout=360 DGCDeadLock
*/
@@ -55,11 +55,12 @@
import java.io.*;
public class DGCDeadLock implements Runnable {
- private static final int REGISTRY_PORT = TestLibrary.getUnusedRandomPort();
final static public int HOLD_TARGET_TIME = 25000;
- public static int TEST_FAIL_TIME = HOLD_TARGET_TIME + 30000;
- public static boolean finished = false;
- static DGCDeadLock test = new DGCDeadLock();
+ public static final double TEST_FAIL_TIME =
+ (HOLD_TARGET_TIME + 30000) * TestLibrary.getTimeoutFactor();
+ public static volatile boolean finished = false;
+ static final DGCDeadLock test = new DGCDeadLock();
+ static volatile int registryPort = -1;
static {
System.setProperty("sun.rmi.transport.cleanInterval", "50");
@@ -67,7 +68,7 @@
static public void main(String[] args) {
- JavaVM testImplVM = null;
+ REGISTRY testImplVM = null;
System.err.println("\nregression test for 4118056\n");
TestLibrary.suggestSecurityManager("java.rmi.RMISecurityManager");
@@ -75,18 +76,15 @@
try {
String options = " -Djava.security.policy=" +
TestParams.defaultPolicy +
- " --add-exports java.rmi/sun.rmi.registry=ALL-UNNAMED" +
- " --add-exports java.rmi/sun.rmi.server=ALL-UNNAMED" +
" --add-opens java.rmi/sun.rmi.transport=ALL-UNNAMED" +
- " --add-exports java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED" +
" -Djava.rmi.dgc.leaseValue=500000" +
- " -Dsun.rmi.dgc.checkInterval=" +
+ " -Dsun.rmi.dgc.checkInterval=" +
(HOLD_TARGET_TIME - 5000) +
- " -Drmi.registry.port=" + REGISTRY_PORT +
"" ;
- testImplVM = new JavaVM("TestImpl", options, "");
+ testImplVM = REGISTRY.createREGISTRYWithRunner("TestImpl", options);
testImplVM.start();
+ registryPort = testImplVM.getPort();
synchronized (test) {
Thread t = new Thread(test);
@@ -94,7 +92,7 @@
t.start();
// wait for the remote calls to take place
- test.wait(TEST_FAIL_TIME);
+ test.wait((long)TEST_FAIL_TIME);
}
if (!finished) {
@@ -106,8 +104,12 @@
"finished in time.");
} catch (Exception e) {
- testImplVM = null;
- TestLibrary.bomb("test failed", e);
+ TestLibrary.bomb("test failed in main()", e);
+ } finally {
+ if (testImplVM != null) {
+ testImplVM.shutdown();
+ testImplVM = null;
+ }
}
}
@@ -115,12 +117,9 @@
try {
String echo = null;
- // give the test remote object time to initialize.
- Thread.currentThread().sleep(8000);
-
// create a test client
Test foo = (Test) Naming.lookup("rmi://:" +
- REGISTRY_PORT +
+ registryPort +
"/Foo");
echo = foo.echo("Hello world");
System.err.println("Test object created.");
@@ -139,7 +138,7 @@
//import "Bar"
Test bar = (Test) Naming.lookup("rmi://:" +
- REGISTRY_PORT +
+ registryPort +
"/Bar");
/* infinite loop to show the liveness of Client,
@@ -155,11 +154,16 @@
finished = true;
} catch (RemoteException e) {
+ System.err.println("catch RemoteException");
+ e.printStackTrace();
}
} catch (Exception e) {
- TestLibrary.bomb("test failed", e);
+ TestLibrary.bomb("test failed in run()", e);
} finally {
+ synchronized(this) {
+ notify();
+ }
}
}
}
--- a/jdk/test/java/rmi/transport/dgcDeadLock/TestImpl.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/java/rmi/transport/dgcDeadLock/TestImpl.java Thu Dec 22 18:48:53 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -34,7 +34,7 @@
import java.rmi.registry.*;
import java.rmi.server.*;
-public class TestImpl extends UnicastRemoteObject
+public class TestImpl extends RegistryRunner
implements Test {
static Thread locker = null;
static TestImpl foo = null;
@@ -53,12 +53,8 @@
}
static public void main(String[] args) {
- Registry registry = null;
-
try {
- int registryPort = Integer.parseInt(System.getProperty("rmi.registry.port"));
- registry = java.rmi.registry.LocateRegistry.
- createRegistry(registryPort);
+ int registryPort = RegistryRunner.init(args);
//export "Foo"
foo = new TestImpl();
@@ -75,16 +71,11 @@
} catch (Exception e) {
throw new RemoteException(e.getMessage());
}
- Thread.sleep(DGCDeadLock.TEST_FAIL_TIME);
- System.err.println("object vm exiting...");
- System.exit(0);
+ RegistryRunner.notify(registryPort);
} catch (Exception e) {
System.err.println(e.getMessage());
e.printStackTrace();
- } finally {
- TestLibrary.unexport(registry);
- registry = null;
}
}
--- a/jdk/test/java/time/tck/java/time/format/TCKLocalizedFieldParser.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/java/time/tck/java/time/format/TCKLocalizedFieldParser.java Thu Dec 22 18:48:53 2016 +0000
@@ -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
@@ -66,9 +66,11 @@
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DateTimeParseException;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
import java.time.temporal.WeekFields;
+import java.util.Locale;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -79,12 +81,17 @@
*/
@Test
public class TCKLocalizedFieldParser extends AbstractTestPrinterParser {
-
+ public static final WeekFields WEEKDEF = WeekFields.of(Locale.US);
+ public static final TemporalField WEEK_BASED_YEAR = WEEKDEF.weekBasedYear();
+ public static final TemporalField WEEK_OF_WEEK_BASED_YEAR = WEEKDEF.weekOfWeekBasedYear();
+ public static final TemporalField DAY_OF_WEEK = WEEKDEF.dayOfWeek();
//-----------------------------------------------------------------------
@DataProvider(name="FieldPatterns")
Object[][] provider_fieldPatterns() {
return new Object[][] {
- {"e", "6", 0, 1, 6},
+ {"e", "6", 0, 1, 6},
+ {"ee", "06", 0, 2, 6},
+ {"c", "6", 0, 1 , 6},
{"W", "3", 0, 1, 3},
{"w", "29", 0, 2, 29},
{"ww", "29", 0, 2, 29},
@@ -99,6 +106,7 @@
WeekFields weekDef = WeekFields.of(locale);
TemporalField field = null;
switch(pattern.charAt(0)) {
+ case 'c' :
case 'e' :
field = weekDef.dayOfWeek();
break;
@@ -176,9 +184,9 @@
{"Y-w-e", "2008-01-1", 0, 9, LocalDate.of(2007, 12, 30)},
{"Y-w-e", "2008-52-1", 0, 9, LocalDate.of(2008, 12, 21)},
{"Y-w-e", "2008-52-7", 0, 9, LocalDate.of(2008, 12, 27)},
- {"Y-w-e", "2009-01-01", 0, 10, LocalDate.of(2008, 12, 28)},
- {"Y-w-e", "2009-01-04", 0, 10, LocalDate.of(2008, 12, 31)},
- {"Y-w-e", "2009-01-05", 0, 10, LocalDate.of(2009, 1, 1)},
+ {"Y-w-e", "2009-01-1", 0, 9, LocalDate.of(2008, 12, 28)},
+ {"Y-w-e", "2009-01-4", 0, 9, LocalDate.of(2008, 12, 31)},
+ {"Y-w-e", "2009-01-5", 0, 9, LocalDate.of(2009, 1, 1)},
};
}
@@ -202,4 +210,77 @@
}
}
+ //-----------------------------------------------------------------------
+ @DataProvider(name = "adjacentValuePatterns1")
+ Object[][] provider_adjacentValuePatterns1() {
+ return new Object[][] {
+ {"YYww", WEEK_BASED_YEAR, WEEK_OF_WEEK_BASED_YEAR, "1612", 2016, 12},
+ {"YYYYww", WEEK_BASED_YEAR, WEEK_OF_WEEK_BASED_YEAR, "201612", 2016, 12},
+ };
+ }
+
+ @Test(dataProvider = "adjacentValuePatterns1")
+ public void test_adjacentValuePatterns1(String pattern, TemporalField field1, TemporalField field2,
+ String text, int expected1, int expected2) {
+ DateTimeFormatter df = new DateTimeFormatterBuilder()
+ .appendPattern(pattern).toFormatter(Locale.US);
+ ParsePosition ppos = new ParsePosition(0);
+ TemporalAccessor parsed = df.parseUnresolved(text, ppos);
+ assertEquals(parsed.get(field1), expected1);
+ assertEquals(parsed.get(field2), expected2);
+ }
+
+ @DataProvider(name = "adjacentValuePatterns2")
+ Object[][] provider_adjacentValuePatterns2() {
+ return new Object[][] {
+ {"YYYYwwc", WEEK_BASED_YEAR, WEEK_OF_WEEK_BASED_YEAR, DAY_OF_WEEK,
+ "2016121", 2016, 12, 1},
+ {"YYYYwwee", WEEK_BASED_YEAR, WEEK_OF_WEEK_BASED_YEAR, DAY_OF_WEEK,
+ "20161201", 2016, 12, 1},
+ {"YYYYwwe", WEEK_BASED_YEAR, WEEK_OF_WEEK_BASED_YEAR, DAY_OF_WEEK,
+ "2016121", 2016, 12, 1},
+ };
+ }
+
+ @Test(dataProvider = "adjacentValuePatterns2")
+ public void test_adjacentValuePatterns2(String pattern, TemporalField field1, TemporalField field2,
+ TemporalField field3, String text, int expected1, int expected2, int expected3) {
+ DateTimeFormatter df = new DateTimeFormatterBuilder()
+ .appendPattern(pattern).toFormatter(Locale.US);
+ ParsePosition ppos = new ParsePosition(0);
+ TemporalAccessor parsed = df.parseUnresolved(text, ppos);
+ assertEquals(parsed.get(field1), expected1);
+ assertEquals(parsed.get(field2), expected2);
+ assertEquals(parsed.get(field3), expected3);
+ }
+
+ @Test
+ public void test_adjacentValuePatterns3() {
+ String pattern = "yyyyMMddwwc";
+ String text = "20120720296";
+ DateTimeFormatter df = new DateTimeFormatterBuilder()
+ .appendPattern(pattern).toFormatter(Locale.US);
+ ParsePosition ppos = new ParsePosition(0);
+ TemporalAccessor parsed = df.parseUnresolved(text, ppos);
+ assertEquals(parsed.get(DAY_OF_WEEK), 6);
+ assertEquals(parsed.get(WEEK_OF_WEEK_BASED_YEAR), 29);
+ LocalDate result = LocalDate.parse(text, df);
+ LocalDate expectedValue = LocalDate.of(2012, 07, 20);
+ assertEquals(result, expectedValue, "LocalDate incorrect for " + pattern);
+ }
+
+ @DataProvider(name = "invalidPatterns")
+ Object[][] provider_invalidPatterns() {
+ return new Object[][] {
+ {"W", "01"},
+ {"c", "01"},
+ {"e", "01"},
+ {"yyyyMMddwwc", "201207202906"}, // 1 extra digit in the input
+ };
+ }
+
+ @Test(dataProvider = "invalidPatterns", expectedExceptions = DateTimeParseException.class)
+ public void test_invalidPatterns(String pattern, String value) {
+ DateTimeFormatter.ofPattern(pattern).parse(value);
+ }
}
--- a/jdk/test/java/util/Currency/CurrencyTest.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/java/util/Currency/CurrencyTest.java Thu Dec 22 18:48:53 2016 +0000
@@ -23,7 +23,7 @@
/*
* @test
* @bug 4290801 4692419 4693631 5101540 5104960 6296410 6336600 6371531
- * 6488442 7036905 8008577 8039317 8074350 8074351 8150324
+ * 6488442 7036905 8008577 8039317 8074350 8074351 8150324 8167143
* @summary Basic tests for Currency class.
* @modules java.base/java.util:open
* jdk.localedata
@@ -188,7 +188,7 @@
static void testSymbols() {
testSymbol("USD", Locale.US, "$");
testSymbol("EUR", Locale.GERMANY, "\u20AC");
- testSymbol("USD", Locale.PRC, "USD");
+ testSymbol("USD", Locale.PRC, "US$");
}
static void testSymbol(String currencyCode, Locale locale, String expectedSymbol) {
@@ -262,7 +262,7 @@
testDisplayName("KRW", Locale.KOREAN, "\ub300\ud55c\ubbfc\uad6d \uc6d0");
testDisplayName("SEK", new Locale("sv"), "svensk krona");
testDisplayName("CNY", Locale.SIMPLIFIED_CHINESE, "\u4eba\u6c11\u5e01");
- testDisplayName("TWD", Locale.TRADITIONAL_CHINESE, "\u65b0\u81fa\u5e63");
+ testDisplayName("TWD", Locale.TRADITIONAL_CHINESE, "\u65b0\u53f0\u5e63");
}
static void testDisplayName(String currencyCode, Locale locale, String expectedName) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/Bug8167143.java Thu Dec 22 18:48:53 2016 +0000
@@ -0,0 +1,279 @@
+/*
+ * 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 8167143
+ * @summary Test
+ * Timezone parsing works for all locales for default providers prefernce
+ * as well as when prefernce list is [COMPAT, CLDR],
+ * CLDR implict locales are correctly reflected,
+ * th_TH bundle is not wrongly cached in DateFormatSymbols,
+ * correct candidate locale list is retrieved for
+ * zh_Hant and zh_Hans and
+ * Implict COMPAT Locales nn-NO, nb-NO are reflected in available locales
+ * for all Providers for COMPAT.
+ * @modules java.base/sun.util.locale.provider
+ * java.base/sun.util.spi
+ * jdk.localedata
+ * @run main/othervm -Djava.locale.providers=COMPAT,CLDR Bug8167143 testTimeZone
+ * @run main/othervm Bug8167143 testTimeZone
+ * @run main/othervm -Djava.locale.providers=CLDR Bug8167143 testCldr
+ * @run main/othervm Bug8167143 testCache
+ * @run main/othervm Bug8167143 testCandidateLocales
+ * @run main/othervm -Djava.locale.providers=COMPAT Bug8167143 testCompat
+ */
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.TimeZone;
+
+import sun.util.locale.provider.LocaleProviderAdapter;
+import sun.util.locale.provider.LocaleProviderAdapter.Type;
+
+public class Bug8167143 {
+
+ private static final TimeZone REYKJAVIK = TimeZone.getTimeZone("Atlantic/Reykjavik");
+ private static final TimeZone NEW_YORK = TimeZone.getTimeZone("America/New_York");
+ private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
+
+ private static final List<Locale> CLDR_IMPLICIT_LOCS = List.of(Locale.forLanguageTag("zh-Hans-CN"),
+ Locale.forLanguageTag("zh-Hans-SG"),
+ Locale.forLanguageTag("zh-Hant-HK"),
+ Locale.forLanguageTag("zh-Hant-TW"),
+ Locale.forLanguageTag("zh-Hant-MO"));
+
+ private static final List<Locale> COMPAT_IMPLICIT_LOCS = List.of(Locale.forLanguageTag("nn-NO"),
+ Locale.forLanguageTag("nb-NO"));
+ /**
+ * List of candidate locales for zh_Hant
+ */
+ private static final List<Locale> ZH_HANT_CANDLOCS = List.of(
+ Locale.forLanguageTag("zh-Hant"),
+ Locale.forLanguageTag("zh-TW"),
+ Locale.forLanguageTag("zh"),
+ Locale.ROOT);
+ /**
+ * List of candidate locales for zh_Hans
+ */
+ private static final List<Locale> ZH_HANS_CANDLOCS = List.of(
+ Locale.forLanguageTag("zh-Hans"),
+ Locale.forLanguageTag("zh-CN"),
+ Locale.forLanguageTag("zh"),
+ Locale.ROOT);
+
+ public static void main(String[] args) {
+ switch (args[0]) {
+ case "testTimeZone":
+ testTimeZoneParsing();
+ break;
+ case "testCldr":
+ testImplicitCldrLocales();
+ break;
+ case "testCache":
+ testDateFormatSymbolsCache();
+ break;
+ case "testCandidateLocales":
+ testCandidateLocales();
+ break;
+ case "testCompat":
+ testImplicitCompatLocales();
+ break;
+ default:
+ throw new RuntimeException("no test was specified.");
+ }
+ }
+
+ /**
+ * Check that if Locale Provider Preference list is Default, or if Locale
+ * Provider Preference List is COMPAT,CLDR SimplDateFormat parsing works for
+ * all Available Locales.
+ */
+ private static void testTimeZoneParsing() {
+ Set<Locale> locales = Set.of(Locale.forLanguageTag("zh-hant"), new Locale("no", "NO", "NY"));
+ // Set<Locale> locales = Set.of(Locale.getAvailableLocales());
+ locales.forEach((locale) -> {
+ final SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd z", locale);
+ for (final TimeZone tz : new TimeZone[]{REYKJAVIK, GMT, NEW_YORK}) {
+ try {
+ sdf.parse("2000/02/10 " + tz.getDisplayName(locale));
+ } catch (ParseException e) {
+ throw new RuntimeException("TimeZone Parsing failed with Locale "
+ + locale + " for TimeZone " + tz.getDisplayName(), e);
+ }
+ }
+ });
+ }
+
+ /**
+ * Check that locales implicitly supported from CLDR are reflected in output
+ * from getAvailbleLocales() for each bundle.
+ *
+ */
+ private static void testImplicitCldrLocales() {
+ LocaleProviderAdapter cldr = LocaleProviderAdapter.forType(Type.CLDR);
+ checkPresenceCldr("CurrencyNameProvider",
+ cldr.getCurrencyNameProvider().getAvailableLocales());
+ checkPresenceCldr("LocaleNameProvider",
+ cldr.getLocaleNameProvider().getAvailableLocales());
+ checkPresenceCldr("TimeZoneNameProvider",
+ cldr.getTimeZoneNameProvider().getAvailableLocales());
+ checkPresenceCldr("CalendarDataProvider",
+ cldr.getCalendarDataProvider().getAvailableLocales());
+ checkPresenceCldr("CalendarNameProvider",
+ cldr.getCalendarProvider().getAvailableLocales());
+ }
+
+ private static void checkPresenceCldr(String testName, Locale[] got) {
+ List<Locale> gotLocalesList = Arrays.asList(got);
+ List<Locale> gotList = new ArrayList<>(gotLocalesList);
+ if (!testName.equals("TimeZoneNameProvider")) {
+ if (!gotList.removeAll(CLDR_IMPLICIT_LOCS)) {
+ // check which locale are not present in retrievedLocales List.
+ List<Locale> expectedLocales = new ArrayList<>(CLDR_IMPLICIT_LOCS);
+ expectedLocales.removeAll(gotList);
+ throw new RuntimeException("Locales those not correctly reflected are "
+ + expectedLocales + " for test " + testName);
+ }
+ } else {
+ // check one extra locale zh_HK for TimeZoneNameProvider
+ Locale zh_HK = Locale.forLanguageTag("zh-HK");
+ if (!gotList.removeAll(CLDR_IMPLICIT_LOCS) && gotList.remove(zh_HK)) {
+ //check which locale are not present in retrievedLocales List
+ List<Locale> expectedLocales = new ArrayList<>(CLDR_IMPLICIT_LOCS);
+ expectedLocales.add(zh_HK);
+ expectedLocales.removeAll(gotList);
+ throw new RuntimeException("Locales those not correctly reflected are "
+ + expectedLocales + " for test " + testName);
+ }
+ }
+ }
+
+ /**
+ * Check that if Locale Provider Preference list is default and if
+ * SimpleDateFormat instance for th-TH-TH is created first, then JRE bundle
+ * for th-TH should not be cached in cache of DateFormatSymbols class.
+ */
+ private static void testDateFormatSymbolsCache() {
+ Locale th_TH_TH = new Locale("th", "TH", "TH");
+ Locale th_TH = new Locale("th", "TH");
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd z", th_TH_TH);
+ String[][] thTHTHZoneStrings = sdf.getDateFormatSymbols().getZoneStrings();
+ String[][] thTHZoneStrings = sdf.getDateFormatSymbols().getZoneStrings();
+ if (Arrays.equals(thTHTHZoneStrings, thTHZoneStrings)) {
+ throw new RuntimeException("th_TH bundle still cached with DateFormatSymbols"
+ + "cache for locale " + th_TH
+ );
+ }
+ }
+
+ /**
+ * Check that candidate locales list retrieved for zh__Hant and for zh__Hans
+ * do not have first candidate locale as zh_TW_Hant and zh_CN_Hans
+ * respectively.
+ */
+ private static void testCandidateLocales() {
+ ResourceBundle.Control Control = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT);
+ Locale zh_Hant = Locale.forLanguageTag("zh-Hant");
+ Locale zh_Hans = Locale.forLanguageTag("zh-Hans");
+ List<Locale> zhHantCandidateLocs = Control.getCandidateLocales("", zh_Hant);
+ List<Locale> zhHansCandidateLocs = Control.getCandidateLocales("", zh_Hans);
+ if (!zhHantCandidateLocs.equals(ZH_HANT_CANDLOCS)) {
+ reportDifference(zhHantCandidateLocs, ZH_HANT_CANDLOCS, "zh_Hant");
+
+ }
+ if (!zhHansCandidateLocs.equals(ZH_HANS_CANDLOCS)) {
+ reportDifference(zhHansCandidateLocs, ZH_HANS_CANDLOCS, "zh_Hans");
+
+ }
+ }
+
+ private static void reportDifference(List<Locale> got, List<Locale> expected, String locale) {
+ List<Locale> retrievedList = new ArrayList<>(got);
+ List<Locale> expectedList = new ArrayList<>(expected);
+ retrievedList.removeAll(expectedList);
+ expectedList.removeAll(retrievedList);
+ if ((retrievedList.size() > 0) && (expectedList.size() > 0)) {
+ throw new RuntimeException(" retrievedList contain extra candidate locales " + retrievedList
+ + " and missing candidate locales " + expectedList
+ + "for locale " + locale);
+ }
+ if ((retrievedList.size() > 0)) {
+ throw new RuntimeException(" retrievedList contain extra candidate locales " + retrievedList
+ + "for locale " + locale);
+ }
+ if ((expectedList.size() > 0)) {
+ throw new RuntimeException(" retrievedList contain extra candidate locales " + expectedList
+ + "for locale " + locale);
+ }
+ }
+
+ /**
+ * checks that locales nn-NO and nb-NO should be present in list of supported locales for
+ * all Providers for COMPAT.
+ */
+ private static void testImplicitCompatLocales() {
+ LocaleProviderAdapter jre = LocaleProviderAdapter.forJRE();
+ checkPresenceCompat("BreakIteratorProvider",
+ jre.getBreakIteratorProvider().getAvailableLocales());
+ checkPresenceCompat("CollatorProvider",
+ jre.getCollatorProvider().getAvailableLocales());
+ checkPresenceCompat("DateFormatProvider",
+ jre.getDateFormatProvider().getAvailableLocales());
+ checkPresenceCompat("DateFormatSymbolsProvider",
+ jre.getDateFormatSymbolsProvider().getAvailableLocales());
+ checkPresenceCompat("DecimalFormatSymbolsProvider",
+ jre.getDecimalFormatSymbolsProvider().getAvailableLocales());
+ checkPresenceCompat("NumberFormatProvider",
+ jre.getNumberFormatProvider().getAvailableLocales());
+ checkPresenceCompat("CurrencyNameProvider",
+ jre.getCurrencyNameProvider().getAvailableLocales());
+ checkPresenceCompat("LocaleNameProvider",
+ jre.getLocaleNameProvider().getAvailableLocales());
+ checkPresenceCompat("TimeZoneNameProvider",
+ jre.getTimeZoneNameProvider().getAvailableLocales());
+ checkPresenceCompat("CalendarDataProvider",
+ jre.getCalendarDataProvider().getAvailableLocales());
+ checkPresenceCompat("CalendarNameProvider",
+ jre.getCalendarNameProvider().getAvailableLocales());
+ checkPresenceCompat("CalendarProvider",
+ jre.getCalendarProvider().getAvailableLocales());
+ }
+
+ private static void checkPresenceCompat(String testName, Locale[] got) {
+ List<Locale> gotLocalesList = Arrays.asList(got);
+ List<Locale> gotList = new ArrayList<>(gotLocalesList);
+ if (!gotList.removeAll(COMPAT_IMPLICIT_LOCS)) {
+ // check which Implicit locale are not present in retrievedLocales List.
+ List<Locale> implicitLocales = new ArrayList<>(COMPAT_IMPLICIT_LOCS);
+ implicitLocales.removeAll(gotList);
+ throw new RuntimeException("Locales those not correctly reflected are "
+ + implicitLocales + " for test " + testName);
+ }
+ }
+}
--- a/jdk/test/java/util/concurrent/tck/Collection8Test.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/java/util/concurrent/tck/Collection8Test.java Thu Dec 22 18:48:53 2016 +0000
@@ -39,6 +39,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.ConcurrentModificationException;
import java.util.Deque;
import java.util.HashSet;
import java.util.Iterator;
@@ -369,9 +370,112 @@
}
/**
+ * All elements removed in the middle of CONCURRENT traversal.
+ */
+ public void testElementRemovalDuringTraversal() {
+ Collection c = impl.emptyCollection();
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ int n = rnd.nextInt(6);
+ ArrayList copy = new ArrayList();
+ for (int i = 0; i < n; i++) {
+ Object x = impl.makeElement(i);
+ copy.add(x);
+ c.add(x);
+ }
+ ArrayList iterated = new ArrayList();
+ ArrayList spliterated = new ArrayList();
+ Spliterator s = c.spliterator();
+ Iterator it = c.iterator();
+ for (int i = rnd.nextInt(n + 1); --i >= 0; ) {
+ assertTrue(s.tryAdvance(spliterated::add));
+ if (rnd.nextBoolean()) assertTrue(it.hasNext());
+ iterated.add(it.next());
+ }
+ Consumer alwaysThrows = e -> { throw new AssertionError(); };
+ if (s.hasCharacteristics(Spliterator.CONCURRENT)) {
+ c.clear(); // TODO: many more removal methods
+ if (testImplementationDetails
+ && !(c instanceof java.util.concurrent.ArrayBlockingQueue)) {
+ if (rnd.nextBoolean())
+ assertFalse(s.tryAdvance(alwaysThrows));
+ else
+ s.forEachRemaining(alwaysThrows);
+ }
+ if (it.hasNext()) iterated.add(it.next());
+ if (rnd.nextBoolean()) assertIteratorExhausted(it);
+ }
+ assertTrue(copy.containsAll(iterated));
+ assertTrue(copy.containsAll(spliterated));
+ }
+
+ /**
+ * Some elements randomly disappear in the middle of traversal.
+ */
+ public void testRandomElementRemovalDuringTraversal() {
+ Collection c = impl.emptyCollection();
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ int n = rnd.nextInt(6);
+ ArrayList copy = new ArrayList();
+ for (int i = 0; i < n; i++) {
+ Object x = impl.makeElement(i);
+ copy.add(x);
+ c.add(x);
+ }
+ ArrayList iterated = new ArrayList();
+ ArrayList spliterated = new ArrayList();
+ ArrayList removed = new ArrayList();
+ Spliterator s = c.spliterator();
+ Iterator it = c.iterator();
+ if (! (s.hasCharacteristics(Spliterator.CONCURRENT) ||
+ s.hasCharacteristics(Spliterator.IMMUTABLE)))
+ return;
+ for (int i = rnd.nextInt(n + 1); --i >= 0; ) {
+ assertTrue(s.tryAdvance(e -> {}));
+ if (rnd.nextBoolean()) assertTrue(it.hasNext());
+ it.next();
+ }
+ Consumer alwaysThrows = e -> { throw new AssertionError(); };
+ // TODO: many more removal methods
+ if (rnd.nextBoolean()) {
+ for (Iterator z = c.iterator(); z.hasNext(); ) {
+ Object e = z.next();
+ if (rnd.nextBoolean()) {
+ try {
+ z.remove();
+ } catch (UnsupportedOperationException ok) { return; }
+ removed.add(e);
+ }
+ }
+ } else {
+ Predicate randomlyRemove = e -> {
+ if (rnd.nextBoolean()) { removed.add(e); return true; }
+ else return false;
+ };
+ c.removeIf(randomlyRemove);
+ }
+ s.forEachRemaining(spliterated::add);
+ while (it.hasNext())
+ iterated.add(it.next());
+ assertTrue(copy.containsAll(iterated));
+ assertTrue(copy.containsAll(spliterated));
+ assertTrue(copy.containsAll(removed));
+ if (s.hasCharacteristics(Spliterator.CONCURRENT)) {
+ ArrayList iteratedAndRemoved = new ArrayList(iterated);
+ ArrayList spliteratedAndRemoved = new ArrayList(spliterated);
+ iteratedAndRemoved.retainAll(removed);
+ spliteratedAndRemoved.retainAll(removed);
+ assertTrue(iteratedAndRemoved.size() <= 1);
+ assertTrue(spliteratedAndRemoved.size() <= 1);
+ if (testImplementationDetails
+ && !(c instanceof java.util.concurrent.ArrayBlockingQueue))
+ assertTrue(spliteratedAndRemoved.isEmpty());
+ }
+ }
+
+ /**
* Various ways of traversing a collection yield same elements
*/
- public void testIteratorEquivalence() {
+ public void testTraversalEquivalence() {
Collection c = impl.emptyCollection();
ThreadLocalRandom rnd = ThreadLocalRandom.current();
int n = rnd.nextInt(6);
@@ -439,6 +543,43 @@
}
/**
+ * Iterator.forEachRemaining has same behavior as Iterator's
+ * default implementation.
+ */
+ public void testForEachRemainingConsistentWithDefaultImplementation() {
+ Collection c = impl.emptyCollection();
+ if (!testImplementationDetails
+ || c.getClass() == java.util.LinkedList.class)
+ return;
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ int n = 1 + rnd.nextInt(3);
+ for (int i = 0; i < n; i++) c.add(impl.makeElement(i));
+ ArrayList iterated = new ArrayList();
+ ArrayList iteratedForEachRemaining = new ArrayList();
+ Iterator it1 = c.iterator();
+ Iterator it2 = c.iterator();
+ assertTrue(it1.hasNext());
+ assertTrue(it2.hasNext());
+ c.clear();
+ Object r1, r2;
+ try {
+ while (it1.hasNext()) iterated.add(it1.next());
+ r1 = iterated;
+ } catch (ConcurrentModificationException ex) {
+ r1 = ConcurrentModificationException.class;
+ assertFalse(impl.isConcurrent());
+ }
+ try {
+ it2.forEachRemaining(iteratedForEachRemaining::add);
+ r2 = iteratedForEachRemaining;
+ } catch (ConcurrentModificationException ex) {
+ r2 = ConcurrentModificationException.class;
+ assertFalse(impl.isConcurrent());
+ }
+ assertEquals(r1, r2);
+ }
+
+ /**
* Calling Iterator#remove() after Iterator#forEachRemaining
* should (maybe) remove last element
*/
@@ -577,6 +718,41 @@
assertTrue(found.isEmpty());
}
+ /** TODO: promote to a common utility */
+ static <T> T chooseOne(T ... ts) {
+ return ts[ThreadLocalRandom.current().nextInt(ts.length)];
+ }
+
+ /** TODO: more random adders and removers */
+ static <E> Runnable adderRemover(Collection<E> c, E e) {
+ return chooseOne(
+ () -> {
+ assertTrue(c.add(e));
+ assertTrue(c.contains(e));
+ assertTrue(c.remove(e));
+ assertFalse(c.contains(e));
+ },
+ () -> {
+ assertTrue(c.add(e));
+ assertTrue(c.contains(e));
+ assertTrue(c.removeIf(x -> x == e));
+ assertFalse(c.contains(e));
+ },
+ () -> {
+ assertTrue(c.add(e));
+ assertTrue(c.contains(e));
+ for (Iterator it = c.iterator();; )
+ if (it.next() == e) {
+ try { it.remove(); }
+ catch (UnsupportedOperationException ok) {
+ c.remove(e);
+ }
+ break;
+ }
+ assertFalse(c.contains(e));
+ });
+ }
+
/**
* Motley crew of threads concurrently randomly hammer the collection.
*/
@@ -616,17 +792,20 @@
() -> checkArraySanity.accept(c.toArray()),
() -> checkArraySanity.accept(c.toArray(emptyArray)),
() -> {
- assertTrue(c.add(one));
- assertTrue(c.contains(one));
- assertTrue(c.remove(one));
- assertFalse(c.contains(one));
- },
- () -> {
- assertTrue(c.add(two));
- assertTrue(c.contains(two));
- assertTrue(c.remove(two));
- assertFalse(c.contains(two));
- },
+ Object[] a = new Object[5];
+ Object three = impl.makeElement(3);
+ Arrays.fill(a, 0, a.length, three);
+ Object[] x = c.toArray(a);
+ if (x == a)
+ for (int i = 0; i < a.length && a[i] != null; i++)
+ checkSanity.accept(a[i]);
+ // A careful reading of the spec does not support:
+ // for (i++; i < a.length; i++) assertSame(three, a[i]);
+ else
+ checkArraySanity.accept(x);
+ },
+ adderRemover(c, one),
+ adderRemover(c, two),
};
final List<Runnable> tasks =
Arrays.stream(frobbers)
@@ -684,6 +863,22 @@
}
}
+ /**
+ * Spliterator.getComparator throws IllegalStateException iff the
+ * spliterator does not report SORTED.
+ */
+ public void testGetComparator_IllegalStateException() {
+ Collection c = impl.emptyCollection();
+ Spliterator s = c.spliterator();
+ boolean reportsSorted = s.hasCharacteristics(Spliterator.SORTED);
+ try {
+ s.getComparator();
+ assertTrue(reportsSorted);
+ } catch (IllegalStateException ex) {
+ assertFalse(reportsSorted);
+ }
+ }
+
// public void testCollection8DebugFail() {
// fail(impl.klazz().getSimpleName());
// }
--- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java Thu Dec 22 18:48:53 2016 +0000
@@ -35,13 +35,30 @@
/*
* @test
- * @summary JSR-166 tck tests
+ * @summary JSR-166 tck tests (conformance testing mode)
+ * @build *
+ * @modules java.management
+ * @run junit/othervm/timeout=1000 JSR166TestCase
+ */
+
+/*
+ * @test
+ * @summary JSR-166 tck tests (whitebox tests allowed)
+ * @build *
* @modules java.base/java.util.concurrent:open
* java.management
- * @build *
- * @run junit/othervm/timeout=1000 -Djsr166.testImplementationDetails=true JSR166TestCase
- * @run junit/othervm/timeout=1000 -Djava.util.concurrent.ForkJoinPool.common.parallelism=0 -Djsr166.testImplementationDetails=true JSR166TestCase
- * @run junit/othervm/timeout=1000 -Djava.util.concurrent.ForkJoinPool.common.parallelism=1 -Djava.util.secureRandomSeed=true JSR166TestCase
+ * @run junit/othervm/timeout=1000
+ * -Djsr166.testImplementationDetails=true
+ * JSR166TestCase
+ * @run junit/othervm/timeout=1000
+ * -Djsr166.testImplementationDetails=true
+ * -Djava.util.concurrent.ForkJoinPool.common.parallelism=0
+ * JSR166TestCase
+ * @run junit/othervm/timeout=1000
+ * -Djsr166.testImplementationDetails=true
+ * -Djava.util.concurrent.ForkJoinPool.common.parallelism=1
+ * -Djava.util.secureRandomSeed=true
+ * JSR166TestCase
*/
import static java.util.concurrent.TimeUnit.MILLISECONDS;
@@ -543,6 +560,8 @@
"DoubleAdderTest",
"ForkJoinPool8Test",
"ForkJoinTask8Test",
+ "LinkedBlockingDeque8Test",
+ "LinkedBlockingQueue8Test",
"LongAccumulatorTest",
"LongAdderTest",
"SplittableRandomTest",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/LinkedBlockingDeque8Test.java Thu Dec 22 18:48:53 2016 +0000
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea and Martin Buchholz with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.Spliterator;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class LinkedBlockingDeque8Test extends JSR166TestCase {
+ public static void main(String[] args) {
+ main(suite(), args);
+ }
+
+ public static Test suite() {
+ return newTestSuite(LinkedBlockingDeque8Test.class);
+ }
+
+ /**
+ * Spliterator.getComparator always throws IllegalStateException
+ */
+ public void testSpliterator_getComparator() {
+ assertThrows(IllegalStateException.class,
+ () -> new LinkedBlockingDeque().spliterator().getComparator());
+ }
+
+ /**
+ * Spliterator characteristics are as advertised
+ */
+ public void testSpliterator_characteristics() {
+ LinkedBlockingDeque q = new LinkedBlockingDeque();
+ Spliterator s = q.spliterator();
+ int characteristics = s.characteristics();
+ int required = Spliterator.CONCURRENT
+ | Spliterator.NONNULL
+ | Spliterator.ORDERED;
+ assertEquals(required, characteristics & required);
+ assertTrue(s.hasCharacteristics(required));
+ assertEquals(0, characteristics
+ & (Spliterator.DISTINCT
+ | Spliterator.IMMUTABLE
+ | Spliterator.SORTED));
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/LinkedBlockingQueue8Test.java Thu Dec 22 18:48:53 2016 +0000
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea and Martin Buchholz with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.Spliterator;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class LinkedBlockingQueue8Test extends JSR166TestCase {
+ public static void main(String[] args) {
+ main(suite(), args);
+ }
+
+ public static Test suite() {
+ return newTestSuite(LinkedBlockingQueue8Test.class);
+ }
+
+ /**
+ * Spliterator.getComparator always throws IllegalStateException
+ */
+ public void testSpliterator_getComparator() {
+ assertThrows(IllegalStateException.class,
+ () -> new LinkedBlockingQueue().spliterator().getComparator());
+ }
+
+ /**
+ * Spliterator characteristics are as advertised
+ */
+ public void testSpliterator_characteristics() {
+ LinkedBlockingQueue q = new LinkedBlockingQueue();
+ Spliterator s = q.spliterator();
+ int characteristics = s.characteristics();
+ int required = Spliterator.CONCURRENT
+ | Spliterator.NONNULL
+ | Spliterator.ORDERED;
+ assertEquals(required, characteristics & required);
+ assertTrue(s.hasCharacteristics(required));
+ assertEquals(0, characteristics
+ & (Spliterator.DISTINCT
+ | Spliterator.IMMUTABLE
+ | Spliterator.SORTED));
+ }
+
+}
--- a/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java Thu Dec 22 18:48:53 2016 +0000
@@ -71,9 +71,9 @@
}
static class CustomTask<V> implements RunnableScheduledFuture<V> {
- RunnableScheduledFuture<V> task;
+ private final RunnableScheduledFuture<V> task;
volatile boolean ran;
- CustomTask(RunnableScheduledFuture<V> t) { task = t; }
+ CustomTask(RunnableScheduledFuture<V> task) { this.task = task; }
public boolean isPeriodic() { return task.isPeriodic(); }
public void run() {
ran = true;
--- a/jdk/test/java/util/concurrent/tck/SubmissionPublisherTest.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/java/util/concurrent/tck/SubmissionPublisherTest.java Thu Dec 22 18:48:53 2016 +0000
@@ -402,6 +402,7 @@
/**
* Closing a publisher exceptionally causes onError to subscribers
+ * after they are subscribed
*/
public void testCloseExceptionallyError() {
SubmissionPublisher<Integer> p = basicPublisher();
@@ -412,9 +413,11 @@
p.submit(1);
p.closeExceptionally(new SPException());
assertTrue(p.isClosed());
+ s1.awaitSubscribe();
s1.awaitError();
assertTrue(s1.nexts <= 1);
assertEquals(1, s1.errors);
+ s2.awaitSubscribe();
s2.awaitError();
assertTrue(s2.nexts <= 1);
assertEquals(1, s2.errors);
--- a/jdk/test/java/util/concurrent/tck/ThreadLocalRandomTest.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/java/util/concurrent/tck/ThreadLocalRandomTest.java Thu Dec 22 18:48:53 2016 +0000
@@ -85,32 +85,41 @@
*/
public void testNext() throws ReflectiveOperationException {
ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ final java.lang.reflect.Method m;
try {
- java.lang.reflect.Method m
- = ThreadLocalRandom.class.getDeclaredMethod(
+ m = ThreadLocalRandom.class.getDeclaredMethod(
"next", new Class[] { int.class });
m.setAccessible(true);
-
- int i;
- {
- int val = new java.util.Random().nextInt(4);
- for (i = 0; i < NCALLS; i++) {
- int q = (int) m.invoke(rnd, new Object[] { 2 });
- if (val == q) break;
- }
- assertTrue(i < NCALLS);
- }
+ } catch (SecurityException acceptable) {
+ // Security manager may deny access
+ return;
+ } catch (Exception ex) {
+ // jdk9 module system may deny access
+ if (ex.getClass().getSimpleName()
+ .equals("InaccessibleObjectException"))
+ return;
+ throw ex;
+ }
- {
- int r = (int) m.invoke(rnd, new Object[] { 3 });
- for (i = 0; i < NCALLS; i++) {
- int q = (int) m.invoke(rnd, new Object[] { 3 });
- assertTrue(q < (1<<3));
- if (r != q) break;
- }
- assertTrue(i < NCALLS);
+ int i;
+ {
+ int val = new java.util.Random().nextInt(4);
+ for (i = 0; i < NCALLS; i++) {
+ int q = (int) m.invoke(rnd, new Object[] { 2 });
+ if (val == q) break;
}
- } catch (SecurityException acceptable) {}
+ assertTrue(i < NCALLS);
+ }
+
+ {
+ int r = (int) m.invoke(rnd, new Object[] { 3 });
+ for (i = 0; i < NCALLS; i++) {
+ int q = (int) m.invoke(rnd, new Object[] { 3 });
+ assertTrue(q < (1<<3));
+ if (r != q) break;
+ }
+ assertTrue(i < NCALLS);
+ }
}
/**
--- a/jdk/test/java/util/concurrent/tck/VectorTest.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/java/util/concurrent/tck/VectorTest.java Thu Dec 22 18:48:53 2016 +0000
@@ -58,9 +58,22 @@
}
}
return newTestSuite(
- // VectorTest.class,
+ VectorTest.class,
CollectionTest.testSuite(new Implementation()),
CollectionTest.testSuite(new SubListImplementation()));
}
+ /**
+ * tests for setSize()
+ */
+ public void testSetSize() {
+ Vector v = new Vector();
+ for (int n : new int[] { 100, 5, 50 }) {
+ v.setSize(n);
+ assertEquals(n, v.size());
+ assertNull(v.get(0));
+ assertNull(v.get(n - 1));
+ }
+ }
+
}
--- a/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java Thu Dec 22 18:48:53 2016 +0000
@@ -176,6 +176,13 @@
}
/*
+ * Configure the server side socket.
+ */
+ protected void configureServerSocket(SSLServerSocket socket) {
+
+ }
+
+ /*
* =============================================
* Define the client and server side operations.
*
@@ -211,6 +218,7 @@
SSLServerSocketFactory sslssf = context.getServerSocketFactory();
SSLServerSocket sslServerSocket =
(SSLServerSocket)sslssf.createServerSocket(serverPort);
+ configureServerSocket(sslServerSocket);
serverPort = sslServerSocket.getLocalPort();
// Signal the client, the server is ready to accept connection.
--- a/jdk/test/javax/swing/JFileChooser/4847375/bug4847375.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/javax/swing/JFileChooser/4847375/bug4847375.java Thu Dec 22 18:48:53 2016 +0000
@@ -23,11 +23,11 @@
/*
* @test
- * @bug 4847375
+ * @bug 4847375 8171363
* @summary JFileChooser Create New Folder button is disabled incorrectly
* @author Pavel Porvatov
* @modules java.desktop/sun.awt
- * java.desktop/sun.awt.shell
+ * java.desktop/sun.awt.shell:+open
*/
import sun.awt.OSInfo;
--- a/jdk/test/javax/swing/JFileChooser/6741890/bug6741890.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/javax/swing/JFileChooser/6741890/bug6741890.java Thu Dec 22 18:48:53 2016 +0000
@@ -22,11 +22,11 @@
*/
/* @test
- @bug 6741890
+ @bug 6741890 8171363
@summary Deadlock in Win32ShellFolderManager2
@author Pavel Porvatov
@modules java.desktop/sun.awt
- java.desktop/sun.awt.shell
+ java.desktop/sun.awt.shell:+open
@run main bug6741890
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JRadioButton/ButtonGroupFocus/ButtonGroupFocusTest.java Thu Dec 22 18:48:53 2016 +0000
@@ -0,0 +1,119 @@
+/*
+ * 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 8074883
+ * @summary Tab key should move to focused button in a button group
+ * @run main ButtonGroupFocusTest
+ */
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.KeyEvent;
+
+public class ButtonGroupFocusTest {
+
+ private static JRadioButton button1;
+ private static JRadioButton button2;
+ private static JRadioButton button3;
+ private static JRadioButton button4;
+ private static JRadioButton button5;
+ private static Robot robot;
+ private static JFrame frame;
+
+ public static void main(String[] args) throws Exception {
+ robot = new Robot();
+ robot.setAutoDelay(100);
+
+ SwingUtilities.invokeAndWait(() -> {
+ frame = new JFrame();
+ Container contentPane = frame.getContentPane();
+ contentPane.setLayout(new FlowLayout());
+ button1 = new JRadioButton("Button 1");
+ contentPane.add(button1);
+ button2 = new JRadioButton("Button 2");
+ contentPane.add(button2);
+ button3 = new JRadioButton("Button 3");
+ contentPane.add(button3);
+ button4 = new JRadioButton("Button 4");
+ contentPane.add(button4);
+ button5 = new JRadioButton("Button 5");
+ contentPane.add(button5);
+ ButtonGroup group = new ButtonGroup();
+ group.add(button1);
+ group.add(button2);
+ group.add(button3);
+
+ group = new ButtonGroup();
+ group.add(button4);
+ group.add(button5);
+
+ button2.setSelected(true);
+
+ frame.pack();
+ frame.setVisible(true);
+ });
+
+ robot.waitForIdle();
+ robot.delay(200);
+
+ SwingUtilities.invokeAndWait(() -> {
+ if( !button2.hasFocus() ) {
+ frame.dispose();
+ throw new RuntimeException(
+ "Button 2 should get focus after activation");
+ }
+ });
+
+ robot.keyPress(KeyEvent.VK_TAB);
+ robot.keyRelease(KeyEvent.VK_TAB);
+
+ robot.waitForIdle();
+ robot.delay(200);
+
+ SwingUtilities.invokeAndWait(() -> {
+ if( !button4.hasFocus() ) {
+ frame.dispose();
+ throw new RuntimeException(
+ "Button 4 should get focus");
+ }
+ button3.setSelected(true);
+ });
+
+ robot.keyPress(KeyEvent.VK_TAB);
+ robot.keyRelease(KeyEvent.VK_TAB);
+
+ robot.waitForIdle();
+ robot.delay(200);
+
+ SwingUtilities.invokeAndWait(() -> {
+ if( !button3.hasFocus() ) {
+ frame.dispose();
+ throw new RuntimeException(
+ "selected Button 3 should get focus");
+ }
+ });
+
+ SwingUtilities.invokeLater(frame::dispose);
+ }
+}
--- a/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java Thu Dec 22 18:48:53 2016 +0000
@@ -29,7 +29,7 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary JavaVM
+ * @build TestLibrary REGISTRY RegistryRunner
* @run main/othervm DeadCachedConnection
*/
@@ -60,73 +60,65 @@
import java.rmi.server.*;
public class DeadCachedConnection {
- static public final int regport = TestLibrary.getUnusedRandomPort();
static public void main(String[] argv)
throws Exception {
- // establish the registry (we hope)
- System.err.println ("Starting registry on port " + regport);
- DeadCachedConnection.makeRegistry(regport);
+ try {
+ Registry reg = null;
+ int port = makeRegistry(0);
- // Get a handle to the registry
- Registry reg = null;
- System.err.println ("Locating just-started registry...");
- try {
- reg = LocateRegistry.getRegistry(regport);
- } catch (RemoteException e) {
- throw new InternalError ("Can't find registry after starting it.");
- }
+ // Get a handle to the registry
+ System.err.println ("Locating just-started registry...");
+ try {
+ reg = LocateRegistry.getRegistry(port);
+ } catch (RemoteException e) {
+ throw new InternalError ("Can't find registry after starting it.");
+ }
+
+ // Contact the registry by invoking something on it.
+ System.err.println ("Connecting to registry...");
+ String[] junk = reg.list();
- // Contact the registry by invoking something on it.
- System.err.println ("Connecting to registry...");
- String[] junk = reg.list();
-
- // Kill and restart the registry
- System.err.println("Killing registry...");
- DeadCachedConnection.killRegistry();
- System.err.println("Restarting registry...");
- DeadCachedConnection.makeRegistry(regport);
+ // Kill and restart the registry
+ System.err.println("Killing registry...");
+ killRegistry();
+ System.err.println("Restarting registry...");
+ makeRegistry(port);
- // Try again (this is the test)
- System.err.println("Trying to use registry in spite of stale cache...");
- junk = reg.list();
+ // Try again (this is the test)
+ System.err.println("Trying to use registry in spite of stale cache...");
+ junk = reg.list();
- // we're happy
- System.err.println("Test succeeded.");
- try {
- DeadCachedConnection.killRegistry();
- } catch (Exception foo) {
+ System.err.println("Test succeeded.");
+ } catch (Exception e) {
+ TestLibrary.bomb(e);
+ } finally {
+ // dont leave the registry around to affect other tests.
+ killRegistry();
}
}
- public static void makeRegistry(int p) {
- // sadly, we can't kill a registry if we have too-close control
- // over it. We must make it in a subprocess, and then kill the
- // subprocess when it has served our needs.
-
+ public static int makeRegistry(int port) {
try {
- JavaVM jvm =
- new JavaVM("sun.rmi.registry.RegistryImpl", "", Integer.toString(p));
- jvm.start();
- DeadCachedConnection.subreg = jvm;
-
+ subreg = REGISTRY.createREGISTRY(System.out, System.err, "", port);
+ subreg.start();
+ int regPort = subreg.getPort();
+ System.out.println("Starting registry on port " + regPort);
+ return regPort;
} catch (IOException e) {
// one of these is summarily dropped, can't remember which one
System.out.println ("Test setup failed - cannot run rmiregistry");
TestLibrary.bomb("Test setup failed - cannot run test", e);
}
- // Slop - wait for registry to come up. This is stupid.
- try {
- Thread.sleep (5000);
- } catch (Exception whatever) {
+ return -1;
+ }
+
+ private static REGISTRY subreg = null;
+
+ public static void killRegistry() throws InterruptedException {
+ if (subreg != null) {
+ subreg.shutdown();
+ subreg = null;
}
}
- private static JavaVM subreg = null;
-
- public static void killRegistry() throws InterruptedException {
- if (DeadCachedConnection.subreg != null) {
- DeadCachedConnection.subreg.terminate();
- }
- DeadCachedConnection.subreg = null;
- }
}
--- a/jdk/test/sun/security/ssl/SSLContextImpl/TrustTrustedCert.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/sun/security/ssl/SSLContextImpl/TrustTrustedCert.java Thu Dec 22 18:48:53 2016 +0000
@@ -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
@@ -32,6 +32,7 @@
* @test
* @bug 7113275 8164846
* @summary compatibility issue with MD2 trust anchor and old X509TrustManager
+ * @library /javax/net/ssl/templates
* @run main/othervm TrustTrustedCert PKIX TLSv1.1 true
* @run main/othervm TrustTrustedCert PKIX TLSv1.1 false
* @run main/othervm TrustTrustedCert SunX509 TLSv1.1 false
@@ -40,7 +41,6 @@
*/
import java.net.*;
-import java.util.*;
import java.io.*;
import javax.net.ssl.*;
import java.security.*;
@@ -49,21 +49,7 @@
import java.security.interfaces.*;
import java.util.Base64;
-
-public class TrustTrustedCert {
-
- /*
- * =============================================================
- * Set the various variables needed for the tests, then
- * specify what tests to run on each side.
- */
-
- /*
- * Should we run the client or server in a separate thread?
- * Both sides can throw exceptions, but do you have a preference
- * as to which side should be the main thread.
- */
- static boolean separateServerThread = false;
+public class TrustTrustedCert extends SSLSocketTemplate {
/*
* Certificates and key used in the test.
@@ -124,89 +110,61 @@
"A5kokFb+E3Gplu29tJvCUpfwgBFRS+wmkvtiaU/tiyDcVgDO+An5DwedxxdVzqiE\n" +
"njWHoKY3axDQ8OU=\n";
-
static char passphrase[] = "passphrase".toCharArray();
- /*
- * Is the server ready to serve?
- */
- volatile static boolean serverReady = false;
-
- /*
- * Turn on SSL debugging?
- */
- static boolean debug = false;
+ @Override
+ protected SSLContext createServerSSLContext() throws Exception {
+ return generateSSLContext();
+ }
- /*
- * Define the server side of the test.
- *
- * If the server prematurely exits, serverReady will be set to true
- * to avoid infinite hangs.
- */
- void doServerSide() throws Exception {
- SSLContext context = generateSSLContext();
- SSLServerSocketFactory sslssf = context.getServerSocketFactory();
- SSLServerSocket sslServerSocket =
- (SSLServerSocket)sslssf.createServerSocket(serverPort);
- sslServerSocket.setNeedClientAuth(true);
- serverPort = sslServerSocket.getLocalPort();
-
- /*
- * Signal Client, we're ready for his connect.
- */
- serverReady = true;
-
- SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
- InputStream sslIS = sslSocket.getInputStream();
- OutputStream sslOS = sslSocket.getOutputStream();
-
- sslIS.read();
- sslOS.write('A');
- sslOS.flush();
-
- sslSocket.close();
+ @Override
+ protected void configureServerSocket(SSLServerSocket socket) {
+ socket.setNeedClientAuth(true);
}
- /*
- * Define the client side of the test.
- *
- * If the server prematurely exits, serverReady will be set to true
- * to avoid infinite hangs.
- */
- void doClientSide() throws Exception {
+ @Override
+ protected void runServerApplication(SSLSocket socket) throws Exception {
+ InputStream sslIS = socket.getInputStream();
+ OutputStream sslOS = socket.getOutputStream();
- /*
- * Wait for server to get started.
- */
- while (!serverReady) {
- Thread.sleep(50);
+ try {
+ sslIS.read();
+ sslOS.write('A');
+ sslOS.flush();
+ } catch (SSLHandshakeException e) {
+ if (expectFail && !e.toString().contains("certificate_unknown")) {
+ throw new RuntimeException(
+ "Expected to see certificate_unknown in exception output",
+ e);
+ }
}
+ }
- SSLSocket sslSocket = null;
- try {
- SSLContext context = generateSSLContext();
- SSLSocketFactory sslsf = context.getSocketFactory();
+ @Override
+ protected SSLContext createClientSSLContext() throws Exception {
+ return generateSSLContext();
+ }
- sslSocket = (SSLSocket)sslsf.createSocket("localhost", serverPort);
+ @Override
+ protected void runClientApplication(SSLSocket socket) throws Exception {
+ // enable the specified TLS protocol
+ socket.setEnabledProtocols(new String[] { tlsProtocol });
- // enable the specified TLS protocol
- sslSocket.setEnabledProtocols(new String[] {tlsProtocol});
+ InputStream sslIS = socket.getInputStream();
+ OutputStream sslOS = socket.getOutputStream();
- InputStream sslIS = sslSocket.getInputStream();
- OutputStream sslOS = sslSocket.getOutputStream();
+ try {
sslOS.write('B');
sslOS.flush();
sslIS.read();
} catch (SSLHandshakeException e) {
- // focus in on the CertPathValidatorException
+ // focus on the CertPathValidatorException
Throwable t = e.getCause().getCause();
- if ((t == null) || (expectFail &&
- !t.toString().contains("MD5withRSA"))) {
+ if ((t == null)
+ || (expectFail && !t.toString().contains("MD5withRSA"))) {
throw new RuntimeException(
- "Expected to see MD5withRSA in exception output " + t);
+ "Expected to see MD5withRSA in exception output", t);
}
- } finally {
- if (sslSocket != null) sslSocket.close();
}
}
@@ -343,13 +301,6 @@
}
}
-
- // use any free port by default
- volatile int serverPort = 0;
-
- volatile Exception serverException = null;
- volatile Exception clientException = null;
-
public static void main(String[] args) throws Exception {
/*
* Get the customized arguments.
@@ -367,144 +318,9 @@
Security.setProperty("jdk.tls.disabledAlgorithms",
"SSLv3, RC4, DH keySize < 768");
- if (debug)
- System.setProperty("javax.net.debug", "all");
-
/*
* Start the tests.
*/
- new TrustTrustedCert();
- }
-
- Thread clientThread = null;
- Thread serverThread = null;
-
- /*
- * Primary constructor, used to drive remainder of the test.
- *
- * Fork off the other side, then do your work.
- */
- TrustTrustedCert() throws Exception {
- try {
- if (separateServerThread) {
- startServer(true);
- startClient(false);
- } else {
- startClient(true);
- startServer(false);
- }
- } catch (Exception e) {
- System.out.println("Unexpected exception: ");
- e.printStackTrace();
- }
-
- /*
- * Wait for other side to close down.
- */
- if (separateServerThread) {
- serverThread.join();
- } else {
- clientThread.join();
- }
-
- /*
- * When we get here, the test is pretty much over.
- * Which side threw the error?
- */
- Exception local;
- Exception remote;
- String whichRemote;
-
- if (separateServerThread) {
- remote = serverException;
- local = clientException;
- whichRemote = "server";
- } else {
- remote = clientException;
- local = serverException;
- whichRemote = "client";
- }
-
- /*
- * If both failed, return the curthread's exception, but also
- * print the remote side Exception
- */
- if ((local != null) && (remote != null)) {
- System.out.println(whichRemote + " also threw:");
- remote.printStackTrace();
- System.out.println();
- throw local;
- }
-
- if (remote != null) {
- throw remote;
- }
-
- if (local != null) {
- throw local;
- }
- }
-
- void startServer(boolean newThread) throws Exception {
- if (newThread) {
- serverThread = new Thread() {
- public void run() {
- try {
- doServerSide();
- } catch (Exception e) {
- /*
- * Our server thread just died.
- *
- * Release the client, if not active already...
- */
- System.err.println("Server died...");
- serverReady = true;
- if (!expectFail) {
- // only record if we weren't expecting.
- // client side will record exception
- serverException = e;
- }
- }
- }
- };
- serverThread.start();
- } else {
- try {
- doServerSide();
- } catch (Exception e) {
- // only record if we weren't expecting.
- // client side will record exception
- if (!expectFail) {
- serverException = e;
- }
- } finally {
- serverReady = true;
- }
- }
- }
-
- void startClient(boolean newThread) throws Exception {
- if (newThread) {
- clientThread = new Thread() {
- public void run() {
- try {
- doClientSide();
- } catch (Exception e) {
- /*
- * Our client thread just died.
- */
- System.err.println("Client died...");
- clientException = e;
- }
- }
- };
- clientThread.start();
- } else {
- try {
- doClientSide();
- } catch (Exception e) {
- clientException = e;
- }
- }
+ new TrustTrustedCert().run();
}
}
--- a/jdk/test/sun/util/locale/provider/Bug8038436.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/sun/util/locale/provider/Bug8038436.java Thu Dec 22 18:48:53 2016 +0000
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8038436 8158504 8065555
+ * @bug 8038436 8158504 8065555 8167143
* @summary Test for changes in 8038436
* @modules java.base/sun.util.locale.provider
* java.base/sun.util.spi
@@ -120,7 +120,7 @@
"fi, fi-FI, fr, fr-BE, fr-CA, fr-CH, fr-FR, ga, ga-IE, he, he-IL, " +
"hi-IN, hr, hr-HR, hu, hu-HU, id, id-ID, is, is-IS, it, it-CH, it-IT, " +
"ja, ja-JP, ko, ko-KR, lt, lt-LT, lv, lv-LV, mk, mk-MK, ms, ms-MY, mt, " +
- "mt-MT, nl, nl-BE, nl-NL, no, no-NO, no-NO, pl, pl-PL, pt, pt-BR, " +
+ "mt-MT, nb-NO, nl, nl-BE, nl-NL, nn-NO, no, no-NO, no-NO, pl, pl-PL, pt, pt-BR, " +
"pt-PT, ro, ro-RO, ru, ru-RU, sk, sk-SK, sl, sl-SI, sq, sq-AL, sr, " +
"sr-BA, sr-CS, sr-Latn, sr-Latn-ME, sr-ME, sr-RS, sv, sv-SE, th, th-TH, " +
"tr, tr-TR, uk, uk-UA, und, vi, vi-VN, zh, zh-CN, zh-HK, zh-Hans-CN, " +
@@ -130,7 +130,7 @@
static final String[] decimalfspLocs = bipLocs;
static final String[] calnpLocs = bipLocs;
static final String[] cpLocs = ("ar, be, bg, ca, cs, da, el, es, et, fi, " +
- "fr, he, hi, hr, hu, is, ja, ko, lt, lv, mk, no, pl, ro, ru, sk, sl, " +
+ "fr, he, hi, hr, hu, is, ja, ko, lt, lv, mk, nb-NO, nn-NO, no, pl, ro, ru, sk, sl, " +
"sq, sr, sr-Latn, sv, th, tr, uk, und, vi, zh, zh-HK, zh-Hant-HK, " +
"zh-Hant-TW, zh-TW, ").split(",\\s*");
static final String[] nfpLocs = ("ar, ar-AE, ar-BH, ar-DZ, ar-EG, ar-IQ, " +
@@ -160,22 +160,22 @@
"es-PA, es-PE, es-PR, es-PY, es-SV, es-US, es-UY, es-VE, et-EE, fi-FI, " +
"fr, fr-BE, fr-CA, fr-CH, fr-FR, fr-LU, ga-IE, he-IL, hi-IN, hr-HR, " +
"hu-HU, id-ID, is-IS, it, it-CH, it-IT, ja, ja-JP, ko, ko-KR, lt-LT, " +
- "lv-LV, mk-MK, ms-MY, mt-MT, nl-BE, nl-NL, no-NO, pl-PL, pt, pt-BR, " +
+ "lv-LV, mk-MK, ms-MY, mt-MT, nb-NO, nl-BE, nl-NL, nn-NO, no-NO, pl-PL, pt, pt-BR, " +
"pt-PT, ro-RO, ru-RU, sk-SK, sl-SI, sq-AL, sr-BA, sr-CS, sr-Latn-BA, " +
"sr-Latn-ME, sr-Latn-RS, sr-ME, sr-RS, sv, sv-SE, th-TH, tr-TR, uk-UA, " +
"und, vi-VN, zh-CN, zh-HK, zh-Hans-CN, zh-Hans-SG, zh-Hant-HK, " +
"zh-Hant-TW, zh-SG, zh-TW, ").split(",\\s*");
static final String[] lnpLocs = ("ar, be, bg, ca, cs, da, de, el, el-CY, " +
"en, en-MT, en-PH, en-SG, es, es-US, et, fi, fr, ga, he, hi, hr, hu, " +
- "id, is, it, ja, ko, lt, lv, mk, ms, mt, nl, no, no-NO, pl, pt, pt-BR, " +
+ "id, is, it, ja, ko, lt, lv, mk, ms, mt, nb-NO, nl, nn-NO, no, no-NO, pl, pt, pt-BR, " +
"pt-PT, ro, ru, sk, sl, sq, sr, sr-Latn, sv, th, tr, uk, und, vi, zh, " +
"zh-HK, zh-Hans-SG, zh-Hant-HK, zh-Hant-TW, zh-SG, zh-TW, ").split(",\\s*");
static final String[] tznpLocs = ("de, en, en-CA, en-GB, en-IE, es, fr, hi, " +
- "it, ja, ko, pt-BR, sv, und, zh-CN, zh-HK, zh-Hans-CN, zh-Hant-HK, " +
+ "it, ja, ko, nb-NO, nn-NO, pt-BR, sv, und, zh-CN, zh-HK, zh-Hans-CN, zh-Hant-HK, " +
"zh-Hant-TW, zh-TW, ").split(",\\s*");
static final String[] caldpLocs = ("ar, be, bg, ca, cs, da, de, el, el-CY, " +
"en, en-GB, en-IE, en-MT, es, es-ES, es-US, et, fi, fr, fr-CA, he, hi, " +
- "hr, hu, id-ID, is, it, ja, ko, lt, lv, mk, ms-MY, mt, mt-MT, nl, no, " +
+ "hr, hu, id-ID, is, it, ja, ko, lt, lv, mk, ms-MY, mt, mt-MT, nb-NO, nl, nn-NO, no, " +
"pl, pt, pt-BR, pt-PT, ro, ru, sk, sl, sq, sr, sr-Latn-BA, sr-Latn-ME, " +
"sr-Latn-RS, sv, th, tr, uk, und, vi, zh, ").split(",\\s*");
static final String[] calpLocs = caldpLocs;
--- a/jdk/test/tools/jmod/JmodTest.java Thu Dec 22 08:26:02 2016 +0000
+++ b/jdk/test/tools/jmod/JmodTest.java Thu Dec 22 18:48:53 2016 +0000
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8142968 8166568
+ * @bug 8142968 8166568 8166286 8170618
* @summary Basic test for jmod
* @library /lib/testlibrary
* @modules jdk.compiler
@@ -114,6 +114,27 @@
.assertSuccess();
}
+ // JDK-8170618 - jmod should validate if any exported or open package is missing
+ @Test
+ public void testMissingPackages() throws IOException {
+ Path apaDir = EXPLODED_DIR.resolve("apa");
+ Path classesDir = EXPLODED_DIR.resolve("apa").resolve("classes");
+ if (Files.exists(classesDir))
+ FileUtils.deleteFileTreeWithRetry(classesDir);
+ assertTrue(compileModule("apa", classesDir));
+ FileUtils.deleteFileTreeWithRetry(classesDir.resolve("jdk"));
+ Path jmod = MODS_DIR.resolve("apa.jmod");
+ jmod("create",
+ "--class-path", classesDir.toString(),
+ jmod.toString())
+ .assertFailure()
+ .resultChecker(r -> {
+ assertContains(r.output, "Packages that are exported or open in apa are not present: [jdk.test.apa]");
+ });
+ if (Files.exists(classesDir))
+ FileUtils.deleteFileTreeWithRetry(classesDir);
+ }
+
@Test
public void testList() throws IOException {
String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();