--- a/jdk/.hgtags Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/.hgtags Thu Apr 13 10:01:46 2017 -0700
@@ -407,3 +407,4 @@
f6bf027e88e9a4dd19f721001a7af00157af42c4 jdk-9+162
50171f8c47961710cbf87aead6f03fa431d8d240 jdk-9+163
6dea581453d7c0e767e3169cfec8b423a381e71d jdk-9+164
+a7942c3b1e59495dbf51dc7c41aab355fcd253d7 jdk-9+165
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/CounterMode.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/CounterMode.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,10 +42,10 @@
* @author Andreas Sterbenz
* @since 1.4.2
*/
-final class CounterMode extends FeedbackCipher {
+class CounterMode extends FeedbackCipher {
// current counter value
- private final byte[] counter;
+ final byte[] counter;
// encrypted bytes of the previous counter value
private final byte[] encryptedCounter;
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/GCTR.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/GCTR.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,52 +29,43 @@
package com.sun.crypto.provider;
-import java.security.*;
-import javax.crypto.*;
+import javax.crypto.IllegalBlockSizeException;
import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE;
/**
* This class represents the GCTR function defined in NIST 800-38D
- * under section 6.5. It needs to be constructed w/ an initialized
- * cipher object, and initial counter block(ICB). Given an input X
- * of arbitrary length, it processes and returns an output which has
- * the same length as X. The invariants of this class are:
- *
- * (1) The length of intialCounterBlk (and also of its clones, e.g.,
- * fields counter and counterSave) is equal to AES_BLOCK_SIZE.
- *
- * (2) After construction, the field counter never becomes null, it
- * always contains a byte array of length AES_BLOCK_SIZE.
+ * under section 6.5. With a given cipher object and initial counter
+ * block, a counter mode operation is performed. Blocksize is limited
+ * to 16 bytes.
*
* If any invariant is broken, failures can occur because the
* AESCrypt.encryptBlock method can be intrinsified on the HotSpot VM
* (see JDK-8067648 for details).
*
+ * The counter mode operations can be intrinsified and parallelized
+ * by using CounterMode.implCrypt() if HotSpot VM supports it on the
+ * architecture.
+ *
* <p>This function is used in the implementation of GCM mode.
*
* @since 1.8
*/
-final class GCTR {
-
- // these fields should not change after the object has been constructed
- private final SymmetricCipher aes;
- private final byte[] icb;
+final class GCTR extends CounterMode {
- // the current counter value
- private byte[] counter;
-
- // needed for save/restore calls
- private byte[] counterSave = null;
-
- // NOTE: cipher should already be initialized
GCTR(SymmetricCipher cipher, byte[] initialCounterBlk) {
- this.aes = cipher;
+ super(cipher);
if (initialCounterBlk.length != AES_BLOCK_SIZE) {
throw new RuntimeException("length of initial counter block (" + initialCounterBlk.length +
") not equal to AES_BLOCK_SIZE (" + AES_BLOCK_SIZE + ")");
}
- this.icb = initialCounterBlk;
- this.counter = icb.clone();
+
+ iv = initialCounterBlk;
+ reset();
+ }
+
+ @Override
+ String getFeedback() {
+ return "GCTR";
}
// input must be multiples of 128-bit blocks when calling update
@@ -89,23 +80,11 @@
throw new RuntimeException("output buffer too small");
}
- byte[] encryptedCntr = new byte[AES_BLOCK_SIZE];
-
- int numOfCompleteBlocks = inLen / AES_BLOCK_SIZE;
- for (int i = 0; i < numOfCompleteBlocks; i++) {
- aes.encryptBlock(counter, 0, encryptedCntr, 0);
- for (int n = 0; n < AES_BLOCK_SIZE; n++) {
- int index = (i * AES_BLOCK_SIZE + n);
- out[outOfs + index] =
- (byte) ((in[inOfs + index] ^ encryptedCntr[n]));
- }
- GaloisCounterMode.increment32(counter);
- }
- return inLen;
+ return encrypt(in, inOfs, inLen, out, outOfs);
}
// input can be arbitrary size when calling doFinal
- protected int doFinal(byte[] in, int inOfs, int inLen, byte[] out,
+ int doFinal(byte[] in, int inOfs, int inLen, byte[] out,
int outOfs) throws IllegalBlockSizeException {
try {
if (inLen < 0) {
@@ -118,7 +97,7 @@
if (lastBlockSize != 0) {
// do the last partial block
byte[] encryptedCntr = new byte[AES_BLOCK_SIZE];
- aes.encryptBlock(counter, 0, encryptedCntr, 0);
+ embeddedCipher.encryptBlock(counter, 0, encryptedCntr, 0);
for (int n = 0; n < lastBlockSize; n++) {
out[outOfs + completeBlkLen + n] =
(byte) ((in[inOfs + completeBlkLen + n] ^
@@ -131,28 +110,4 @@
}
return inLen;
}
-
- /**
- * Resets the content of this object to when it's first constructed.
- */
- void reset() {
- System.arraycopy(icb, 0, counter, 0, icb.length);
- counterSave = null;
- }
-
- /**
- * Save the current content of this object.
- */
- void save() {
- this.counterSave = this.counter.clone();
- }
-
- /**
- * Restores the content of this object to the previous saved one.
- */
- void restore() {
- if (this.counterSave != null) {
- this.counter = this.counterSave;
- }
- }
}
--- a/jdk/src/java.base/share/classes/java/io/FilePermission.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/io/FilePermission.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -209,6 +209,10 @@
private static final Path here = builtInFS.getPath(
GetPropertyAction.privilegedGetProperty("user.dir"));
+ private static final Path EMPTY_PATH = builtInFS.getPath("");
+ private static final Path DASH_PATH = builtInFS.getPath("-");
+ private static final Path DOTDOT_PATH = builtInFS.getPath("..");
+
/**
* A private constructor that clones some and updates some,
* always with a different name.
@@ -341,7 +345,7 @@
.normalize();
// lastName should always be non-null now
Path lastName = npath.getFileName();
- if (lastName != null && lastName.toString().equals("-")) {
+ if (lastName != null && lastName.equals(DASH_PATH)) {
directory = true;
recursive = !rememberStar;
npath = npath.getParent();
@@ -679,23 +683,76 @@
* @return the depth in between
*/
private static int containsPath(Path p1, Path p2) {
- Path p;
- try {
- p = p2.relativize(p1).normalize();
- if (p.getName(0).toString().isEmpty()) {
- return 0;
- } else {
- for (Path item: p) {
- String s = item.toString();
- if (!s.equals("..")) {
- return -1;
- }
- }
- return p.getNameCount();
- }
- } catch (IllegalArgumentException iae) {
+
+ // Two paths must have the same root. For example,
+ // there is no contains relation between any two of
+ // "/x", "x", "C:/x", "C:x", and "//host/share/x".
+ if (!Objects.equals(p1.getRoot(), p2.getRoot())) {
return -1;
}
+
+ // Empty path (i.e. "." or "") is a strange beast,
+ // because its getNameCount()==1 but getName(0) is null.
+ // It's better to deal with it separately.
+ if (p1.equals(EMPTY_PATH)) {
+ if (p2.equals(EMPTY_PATH)) {
+ return 0;
+ } else if (p2.getName(0).equals(DOTDOT_PATH)) {
+ // "." contains p2 iif p2 has no "..". Since a
+ // a normalized path can only have 0 or more
+ // ".." at the beginning. We only need to look
+ // at the head.
+ return -1;
+ } else {
+ // and the distance is p2's name count. i.e.
+ // 3 between "." and "a/b/c".
+ return p2.getNameCount();
+ }
+ } else if (p2.equals(EMPTY_PATH)) {
+ int c1 = p1.getNameCount();
+ if (!p1.getName(c1 - 1).equals(DOTDOT_PATH)) {
+ // "." is inside p1 iif p1 is 1 or more "..".
+ // For the same reason above, we only need to
+ // look at the tail.
+ return -1;
+ }
+ // and the distance is the count of ".."
+ return c1;
+ }
+
+ // Good. No more empty paths.
+
+ // Common heads are removed
+
+ int c1 = p1.getNameCount();
+ int c2 = p2.getNameCount();
+
+ int n = Math.min(c1, c2);
+ int i = 0;
+ while (i < n) {
+ if (!p1.getName(i).equals(p2.getName(i)))
+ break;
+ i++;
+ }
+
+ // for p1 containing p2, p1 must be 0-or-more "..",
+ // and p2 cannot have "..". For the same reason, we only
+ // check tail of p1 and head of p2.
+ if (i < c1 && !p1.getName(c1 - 1).equals(DOTDOT_PATH)) {
+ return -1;
+ }
+
+ if (i < c2 && p2.getName(i).equals(DOTDOT_PATH)) {
+ return -1;
+ }
+
+ // and the distance is the name counts added (after removing
+ // the common heads).
+
+ // For example: p1 = "../../..", p2 = "../a".
+ // After removing the common heads, they become "../.." and "a",
+ // and the distance is (3-1)+(2-1) = 3.
+ return c1 - i + c2 - i;
}
/**
--- a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -307,6 +307,8 @@
* sequence.
*/
public int codePointAt(int index) {
+ int count = this.count;
+ byte[] value = this.value;
checkIndex(index, count);
if (isLatin1()) {
return value[index] & 0xff;
@@ -560,11 +562,7 @@
val[count++] = 'l';
val[count++] = 'l';
} else {
- checkOffset(count + 4, val.length >> 1);
- StringUTF16.putChar(val, count++, 'n');
- StringUTF16.putChar(val, count++, 'u');
- StringUTF16.putChar(val, count++, 'l');
- StringUTF16.putChar(val, count++, 'l');
+ count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
}
this.count = count;
return this;
@@ -695,18 +693,9 @@
}
} else {
if (b) {
- checkOffset(count + 4, val.length >> 1);
- StringUTF16.putChar(val, count++, 't');
- StringUTF16.putChar(val, count++, 'r');
- StringUTF16.putChar(val, count++, 'u');
- StringUTF16.putChar(val, count++, 'e');
+ count = StringUTF16.putCharsAt(val, count, 't', 'r', 'u', 'e');
} else {
- checkOffset(count + 5, val.length >> 1);
- StringUTF16.putChar(val, count++, 'f');
- StringUTF16.putChar(val, count++, 'a');
- StringUTF16.putChar(val, count++, 'l');
- StringUTF16.putChar(val, count++, 's');
- StringUTF16.putChar(val, count++, 'e');
+ count = StringUTF16.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e');
}
}
this.count = count;
@@ -755,16 +744,15 @@
* @return a reference to this object.
*/
public AbstractStringBuilder append(int i) {
+ int count = this.count;
int spaceNeeded = count + Integer.stringSize(i);
ensureCapacityInternal(spaceNeeded);
if (isLatin1()) {
Integer.getChars(i, spaceNeeded, value);
} else {
- byte[] val = this.value;
- checkOffset(spaceNeeded, val.length >> 1);
- Integer.getCharsUTF16(i, spaceNeeded, val);
+ StringUTF16.getChars(i, count, spaceNeeded, value);
}
- count = spaceNeeded;
+ this.count = spaceNeeded;
return this;
}
@@ -781,16 +769,15 @@
* @return a reference to this object.
*/
public AbstractStringBuilder append(long l) {
+ int count = this.count;
int spaceNeeded = count + Long.stringSize(l);
ensureCapacityInternal(spaceNeeded);
if (isLatin1()) {
Long.getChars(l, spaceNeeded, value);
} else {
- byte[] val = this.value;
- checkOffset(spaceNeeded, val.length >> 1);
- Long.getCharsUTF16(l, spaceNeeded, val);
+ StringUTF16.getChars(l, count, spaceNeeded, value);
}
- count = spaceNeeded;
+ this.count = spaceNeeded;
return this;
}
@@ -843,6 +830,7 @@
* greater than {@code end}.
*/
public AbstractStringBuilder delete(int start, int end) {
+ int count = this.count;
if (end > count) {
end = count;
}
@@ -850,7 +838,7 @@
int len = end - start;
if (len > 0) {
shift(end, -len);
- count -= len;
+ this.count = count - len;
}
return this;
}
@@ -925,6 +913,7 @@
* greater than {@code end}.
*/
public AbstractStringBuilder replace(int start, int end, String str) {
+ int count = this.count;
if (end > count) {
end = count;
}
@@ -933,7 +922,7 @@
int newCount = count + len - (end - start);
ensureCapacityInternal(newCount);
shift(end, newCount - count);
- count = newCount;
+ this.count = newCount;
putStringAt(start, str);
return this;
}
@@ -1500,40 +1489,11 @@
val[k] = cj;
}
} else {
- checkOffset(count, val.length >> 1);
- boolean hasSurrogates = false;
- for (int j = (n-1) >> 1; j >= 0; j--) {
- int k = n - j;
- char cj = StringUTF16.getChar(val, j);
- char ck = StringUTF16.getChar(val, k);
- StringUTF16.putChar(val, j, ck);
- StringUTF16.putChar(val, k, cj);
- if (Character.isSurrogate(cj) ||
- Character.isSurrogate(ck)) {
- hasSurrogates = true;
- }
- }
- if (hasSurrogates) {
- reverseAllValidSurrogatePairs(val, count);
- }
+ StringUTF16.reverse(val, count);
}
return this;
}
- /** Outlined helper method for reverse() */
- private void reverseAllValidSurrogatePairs(byte[] val, int count) {
- for (int i = 0; i < count - 1; i++) {
- char c2 = StringUTF16.getChar(val, i);
- if (Character.isLowSurrogate(c2)) {
- char c1 = StringUTF16.getChar(val, i + 1);
- if (Character.isHighSurrogate(c1)) {
- StringUTF16.putChar(val, i++, c1);
- StringUTF16.putChar(val, i, c2);
- }
- }
- }
- }
-
/**
* Returns a string representing the data in this sequence.
* A new {@code String} object is allocated and initialized to
@@ -1682,6 +1642,7 @@
}
private final void appendChars(char[] s, int off, int end) {
+ int count = this.count;
if (isLatin1()) {
byte[] val = this.value;
for (int i = off, j = count; i < end; i++) {
@@ -1689,17 +1650,17 @@
if (StringLatin1.canEncode(c)) {
val[j++] = (byte)c;
} else {
- count = j;
+ this.count = count = j;
inflate();
StringUTF16.putCharsSB(this.value, j, s, i, end);
- count += end - i;
+ this.count = count + end - i;
return;
}
}
} else {
StringUTF16.putCharsSB(this.value, count, s, off, end);
}
- count += end - off;
+ this.count = count + end - off;
}
private final void appendChars(CharSequence s, int off, int end) {
--- a/jdk/src/java.base/share/classes/java/lang/Integer.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/Integer.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -386,7 +386,7 @@
}
/** byte[]/UTF16 version */
- static void formatUnsignedIntUTF16(int val, int shift, byte[] buf, int offset, int len) {
+ private static void formatUnsignedIntUTF16(int val, int shift, byte[] buf, int offset, int len) {
int charPos = offset + len;
int radix = 1 << shift;
int mask = radix - 1;
@@ -442,7 +442,7 @@
return new String(buf, LATIN1);
} else {
byte[] buf = new byte[size * 2];
- getCharsUTF16(i, size, buf);
+ StringUTF16.getChars(i, size, buf);
return new String(buf, UTF16);
}
}
@@ -516,49 +516,6 @@
return charPos;
}
- /**
- * This is a variant of {@link #getChars(int, int, byte[])}, but for
- * UTF-16 coder.
- *
- * @param i value to convert
- * @param index next index, after the least significant digit
- * @param buf target buffer, UTF16-coded.
- * @return index of the most significant digit or minus sign, if present
- */
- static int getCharsUTF16(int i, int index, byte[] buf) {
- int q, r;
- int charPos = index;
-
- boolean negative = (i < 0);
- if (!negative) {
- i = -i;
- }
-
- // Get 2 digits/iteration using ints
- while (i <= -100) {
- q = i / 100;
- r = (q * 100) - i;
- i = q;
- StringUTF16.putChar(buf, --charPos, DigitOnes[r]);
- StringUTF16.putChar(buf, --charPos, DigitTens[r]);
- }
-
- // We know there are at most two digits left at this point.
- q = i / 10;
- r = (q * 10) - i;
- StringUTF16.putChar(buf, --charPos, '0' + r);
-
- // Whatever left is the remaining digit.
- if (q < 0) {
- StringUTF16.putChar(buf, --charPos, '0' - q);
- }
-
- if (negative) {
- StringUTF16.putChar(buf, --charPos, '-');
- }
- return charPos;
- }
-
// Left here for compatibility reasons, see JDK-8143900.
static final int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
--- a/jdk/src/java.base/share/classes/java/lang/Long.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/Long.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -414,7 +414,7 @@
}
/** byte[]/UTF16 version */
- static void formatUnsignedLong0UTF16(long val, int shift, byte[] buf, int offset, int len) {
+ private static void formatUnsignedLong0UTF16(long val, int shift, byte[] buf, int offset, int len) {
int charPos = offset + len;
int radix = 1 << shift;
int mask = radix - 1;
@@ -475,7 +475,7 @@
return new String(buf, LATIN1);
} else {
byte[] buf = new byte[size * 2];
- getCharsUTF16(i, size, buf);
+ StringUTF16.getChars(i, size, buf);
return new String(buf, UTF16);
}
}
@@ -562,61 +562,6 @@
}
/**
- * This is a variant of {@link #getChars(long, int, byte[])}, but for
- * UTF-16 coder.
- *
- * @param i value to convert
- * @param index next index, after the least significant digit
- * @param buf target buffer, UTF16-coded.
- * @return index of the most significant digit or minus sign, if present
- */
- static int getCharsUTF16(long i, int index, byte[] buf) {
- long q;
- int r;
- int charPos = index;
-
- boolean negative = (i < 0);
- if (!negative) {
- i = -i;
- }
-
- // Get 2 digits/iteration using longs until quotient fits into an int
- while (i <= Integer.MIN_VALUE) {
- q = i / 100;
- r = (int)((q * 100) - i);
- i = q;
- StringUTF16.putChar(buf, --charPos, Integer.DigitOnes[r]);
- StringUTF16.putChar(buf, --charPos, Integer.DigitTens[r]);
- }
-
- // Get 2 digits/iteration using ints
- int q2;
- int i2 = (int)i;
- while (i2 <= -100) {
- q2 = i2 / 100;
- r = (q2 * 100) - i2;
- i2 = q2;
- StringUTF16.putChar(buf, --charPos, Integer.DigitOnes[r]);
- StringUTF16.putChar(buf, --charPos, Integer.DigitTens[r]);
- }
-
- // We know there are at most two digits left at this point.
- q2 = i2 / 10;
- r = (q2 * 10) - i2;
- StringUTF16.putChar(buf, --charPos, '0' + r);
-
- // Whatever left is the remaining digit.
- if (q2 < 0) {
- StringUTF16.putChar(buf, --charPos, '0' - q2);
- }
-
- if (negative) {
- StringUTF16.putChar(buf, --charPos, '-');
- }
- return charPos;
- }
-
- /**
* Returns the string representation size for a given long value.
*
* @param x long value
--- a/jdk/src/java.base/share/classes/java/lang/Process.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/Process.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -80,10 +80,10 @@
*
* <p>Subclasses of Process should override the {@link #onExit()} and
* {@link #toHandle()} methods to provide a fully functional Process including the
- * {@link #getPid() process id},
- * {@link #info() information about the process},
- * {@link #children() direct children}, and
- * {@link #descendants() direct children plus descendants of those children} of the process.
+ * {@linkplain #pid() process id},
+ * {@linkplain #info() information about the process},
+ * {@linkplain #children() direct children}, and
+ * {@linkplain #descendants() direct children plus descendants of those children} of the process.
* Delegating to the underlying Process or ProcessHandle is typically
* easiest and most efficient.
*
@@ -237,14 +237,14 @@
/**
* Kills the process.
* Whether the process represented by this {@code Process} object is
- * {@link #supportsNormalTermination normally terminated} or not is
+ * {@linkplain #supportsNormalTermination normally terminated} or not is
* implementation dependent.
* Forcible process destruction is defined as the immediate termination of a
* process, whereas normal termination allows the process to shut down cleanly.
* If the process is not alive, no action is taken.
* <p>
* The {@link java.util.concurrent.CompletableFuture} from {@link #onExit} is
- * {@link java.util.concurrent.CompletableFuture#complete completed}
+ * {@linkplain java.util.concurrent.CompletableFuture#complete completed}
* when the process has terminated.
*/
public abstract void destroy();
@@ -257,7 +257,7 @@
* If the process is not alive, no action is taken.
* <p>
* The {@link java.util.concurrent.CompletableFuture} from {@link #onExit} is
- * {@link java.util.concurrent.CompletableFuture#complete completed}
+ * {@linkplain java.util.concurrent.CompletableFuture#complete completed}
* when the process has terminated.
* <p>
* Invoking this method on {@code Process} objects returned by
@@ -335,15 +335,15 @@
*
* @implSpec
* The implementation of this method returns the process id as:
- * {@link #toHandle toHandle().getPid()}.
+ * {@link #toHandle toHandle().pid()}.
*
* @return the native process id of the process
* @throws UnsupportedOperationException if the Process implementation
* does not support this operation
* @since 9
*/
- public long getPid() {
- return toHandle().getPid();
+ public long pid() {
+ return toHandle().pid();
}
/**
@@ -357,9 +357,9 @@
* <p>
* Calling {@code onExit().get()} waits for the process to terminate and returns
* the Process. The future can be used to check if the process is
- * {@link java.util.concurrent.CompletableFuture#isDone done} or to
- * {@link java.util.concurrent.CompletableFuture#get() wait} for it to terminate.
- * {@link java.util.concurrent.CompletableFuture#cancel(boolean) Cancelling}
+ * {@linkplain java.util.concurrent.CompletableFuture#isDone done} or to
+ * {@linkplain java.util.concurrent.CompletableFuture#get() wait} for it to terminate.
+ * {@linkplain java.util.concurrent.CompletableFuture#cancel(boolean) Cancelling}
* the CompletableFuture does not affect the Process.
* <p>
* Processes returned from {@link ProcessBuilder#start} override the
@@ -389,7 +389,7 @@
* {@code waitFor} is interrupted, the thread's interrupt status is preserved.
* <p>
* When {@link #waitFor()} returns successfully the CompletableFuture is
- * {@link java.util.concurrent.CompletableFuture#complete completed} regardless
+ * {@linkplain java.util.concurrent.CompletableFuture#complete completed} regardless
* of the exit status of the process.
*
* This implementation may consume a lot of memory for thread stacks if a
@@ -463,7 +463,7 @@
* This implementation throws an instance of
* {@link java.lang.UnsupportedOperationException} and performs no other action.
* Subclasses should override this method to provide a ProcessHandle for the
- * process. The methods {@link #getPid}, {@link #info}, {@link #children},
+ * process. The methods {@link #pid}, {@link #info}, {@link #children},
* and {@link #descendants}, unless overridden, operate on the ProcessHandle.
*
* @return Returns a ProcessHandle for the Process
@@ -500,10 +500,10 @@
/**
* Returns a snapshot of the direct children of the process.
* The parent of a direct child process is the process.
- * Typically, a process that is {@link #isAlive not alive} has no children.
+ * Typically, a process that is {@linkplain #isAlive not alive} has no children.
* <p>
* <em>Note that processes are created and terminate asynchronously.
- * There is no guarantee that a process is {@link #isAlive alive}.
+ * There is no guarantee that a process is {@linkplain #isAlive alive}.
* </em>
*
* @implSpec
@@ -526,10 +526,10 @@
* Returns a snapshot of the descendants of the process.
* The descendants of a process are the children of the process
* plus the descendants of those children, recursively.
- * Typically, a process that is {@link #isAlive not alive} has no children.
+ * Typically, a process that is {@linkplain #isAlive not alive} has no children.
* <p>
* <em>Note that processes are created and terminate asynchronously.
- * There is no guarantee that a process is {@link #isAlive alive}.
+ * There is no guarantee that a process is {@linkplain #isAlive alive}.
* </em>
*
* @implSpec
--- a/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -104,7 +104,7 @@
* @throws UnsupportedOperationException if the implementation
* does not support this operation
*/
- long getPid();
+ long pid();
/**
* Returns an {@code Optional<ProcessHandle>} for an existing native process.
@@ -383,7 +383,7 @@
/**
* Returns a hash code value for this ProcessHandle.
* The hashcode value follows the general contract for {@link Object#hashCode()}.
- * The value is a function of the {@link #getPid getPid()} value and
+ * The value is a function of the {@link #pid pid()} value and
* may be a function of additional information to uniquely identify the process.
* If two ProcessHandles are equal according to the {@link #equals(Object) equals}
* method, then calling the hashCode method on each of the two objects
--- a/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java Thu Apr 13 10:01:46 2017 -0700
@@ -35,11 +35,7 @@
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
-import java.util.concurrent.ForkJoinPool;
-import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
import java.util.stream.Stream;
@@ -176,7 +172,7 @@
throw new IllegalStateException("onExit for current process not allowed");
}
- return ProcessHandleImpl.completion(getPid(), false)
+ return ProcessHandleImpl.completion(pid(), false)
.handleAsync((exitStatus, unusedThrowable) -> this);
}
@@ -259,7 +255,7 @@
* @return the native process ID
*/
@Override
- public long getPid() {
+ public long pid() {
return pid;
}
--- a/jdk/src/java.base/share/classes/java/lang/String.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/String.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1064,11 +1064,7 @@
if (!isLatin1()) { // utf16 str and latin1 abs can never be "equal"
return false;
}
- for (int i = 0; i < len; i++) {
- if ((char)(v1[i] & 0xff) != StringUTF16.getChar(v2, i)) {
- return false;
- }
- }
+ return StringUTF16.contentEquals(v1, v2, len);
}
return true;
}
@@ -1120,10 +1116,8 @@
}
}
} else {
- for (int i = 0; i < n; i++) {
- if (StringUTF16.getChar(val, i) != cs.charAt(i)) {
- return false;
- }
+ if (!StringUTF16.contentEquals(val, cs, n)) {
+ return false;
}
}
return true;
@@ -1734,6 +1728,9 @@
if (tgtCount == 0) {
return fromIndex;
}
+ if (tgtCount > srcCount) {
+ return -1;
+ }
if (srcCoder == tgtCoder) {
return srcCoder == LATIN1
? StringLatin1.indexOf(src, srcCount, tgt, tgtCount, fromIndex)
@@ -1792,7 +1789,7 @@
* is the string being searched for.
*
* @param src the characters being searched.
- * @param srcCoder coder handles the mapping between bytes/chars
+ * @param srcCoder coder handles the mapping between bytes/chars
* @param srcCount count of the source string.
* @param tgt the characters being searched for.
* @param fromIndex the index to begin searching from.
@@ -1807,12 +1804,12 @@
* consistency, don't check for null str.
*/
int rightIndex = srcCount - tgtCount;
+ if (fromIndex > rightIndex) {
+ fromIndex = rightIndex;
+ }
if (fromIndex < 0) {
return -1;
}
- if (fromIndex > rightIndex) {
- fromIndex = rightIndex;
- }
/* Empty string always matches. */
if (tgtCount == 0) {
return fromIndex;
@@ -1825,31 +1822,8 @@
if (srcCoder == LATIN1) { // && tgtCoder == UTF16
return -1;
}
- // srcCoder == UTF16 && tgtCoder == LATIN1
- int min = tgtCount - 1;
- int i = min + fromIndex;
- int strLastIndex = tgtCount - 1;
-
- char strLastChar = (char)(tgt[strLastIndex] & 0xff);
- startSearchForLastChar:
- while (true) {
- while (i >= min && StringUTF16.getChar(src, i) != strLastChar) {
- i--;
- }
- if (i < min) {
- return -1;
- }
- int j = i - 1;
- int start = j - strLastIndex;
- int k = strLastIndex - 1;
- while (j > start) {
- if (StringUTF16.getChar(src, j--) != (tgt[k--] & 0xff)) {
- i--;
- continue startSearchForLastChar;
- }
- }
- return start + 1;
- }
+ // srcCoder == UTF16 && tgtCoder == LATIN1
+ return StringUTF16.lastIndexOfLatin1(src, srcCount, tgt, tgtCount, fromIndex);
}
/**
@@ -3078,7 +3052,8 @@
*/
static void checkIndex(int index, int length) {
if (index < 0 || index >= length) {
- throw new StringIndexOutOfBoundsException("index " + index);
+ throw new StringIndexOutOfBoundsException("index " + index +
+ ",length " + length);
}
}
@@ -3116,7 +3091,7 @@
* If {@code begin} is negative, {@code begin} is greater than
* {@code end}, or {@code end} is greater than {@code length}.
*/
- private static void checkBoundsBeginEnd(int begin, int end, int length) {
+ static void checkBoundsBeginEnd(int begin, int end, int length) {
if (begin < 0 || begin > end || end > length) {
throw new StringIndexOutOfBoundsException(
"begin " + begin + ", end " + end + ", length " + length);
--- a/jdk/src/java.base/share/classes/java/lang/StringConcatHelper.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/StringConcatHelper.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -293,7 +293,7 @@
if (coder == String.LATIN1) {
return Integer.getChars(value, index, buf);
} else {
- return Integer.getCharsUTF16(value, index, buf);
+ return StringUTF16.getChars(value, index, buf);
}
}
@@ -311,7 +311,7 @@
if (coder == String.LATIN1) {
return Long.getChars(value, index, buf);
} else {
- return Long.getCharsUTF16(value, index, buf);
+ return StringUTF16.getChars(value, index, buf);
}
}
--- a/jdk/src/java.base/share/classes/java/lang/StringLatin1.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/StringLatin1.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,6 @@
import static java.lang.String.LATIN1;
import static java.lang.String.UTF16;
import static java.lang.String.checkOffset;
-import static java.lang.String.checkBoundsOffCount;
final class StringLatin1 {
@@ -566,11 +565,7 @@
// inflatedCopy byte[] -> byte[]
@HotSpotIntrinsicCandidate
public static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
- // We need a range check here because 'putChar' has no checks
- checkBoundsOffCount(dstOff << 1, len << 1, dst.length);
- for (int i = 0; i < len; i++) {
- StringUTF16.putChar(dst, dstOff++, src[srcOff++] & 0xff);
- }
+ StringUTF16.inflate(src, srcOff, dst, dstOff, len);
}
static class CharsSpliterator implements Spliterator.OfInt {
--- a/jdk/src/java.base/share/classes/java/lang/StringUTF16.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/StringUTF16.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,12 +30,11 @@
import java.util.Spliterator;
import java.util.function.IntConsumer;
import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.vm.annotation.ForceInline;
+import jdk.internal.vm.annotation.DontInline;
import static java.lang.String.UTF16;
import static java.lang.String.LATIN1;
-import static java.lang.String.checkIndex;
-import static java.lang.String.checkOffset;
-import static java.lang.String.checkBoundsOffCount;
final class StringUTF16 {
@@ -51,33 +50,37 @@
}
@HotSpotIntrinsicCandidate
- public static void putChar(byte[] val, int index, int c) {
+ // intrinsic performs no bounds checks
+ static void putChar(byte[] val, int index, int c) {
+ assert index >= 0 && index < length(val) : "Trusted caller missed bounds check";
index <<= 1;
val[index++] = (byte)(c >> HI_BYTE_SHIFT);
val[index] = (byte)(c >> LO_BYTE_SHIFT);
}
@HotSpotIntrinsicCandidate
- public static char getChar(byte[] val, int index) {
+ // intrinsic performs no bounds checks
+ static char getChar(byte[] val, int index) {
+ assert index >= 0 && index < length(val) : "Trusted caller missed bounds check";
index <<= 1;
return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) |
((val[index] & 0xff) << LO_BYTE_SHIFT));
}
- public static char charAt(byte[] value, int index) {
- if (index < 0 || index >= value.length >> 1) {
- throw new StringIndexOutOfBoundsException(index);
- }
- return getChar(value, index);
- }
-
public static int length(byte[] value) {
return value.length >> 1;
}
- public static int codePointAt(byte[] value, int index, int end) {
+ private static int codePointAt(byte[] value, int index, int end, boolean checked) {
+ assert index < end;
+ if (checked) {
+ checkIndex(index, value);
+ }
char c1 = getChar(value, index);
if (Character.isHighSurrogate(c1) && ++index < end) {
+ if (checked) {
+ checkIndex(index, value);
+ }
char c2 = getChar(value, index);
if (Character.isLowSurrogate(c2)) {
return Character.toCodePoint(c1, c2);
@@ -86,10 +89,22 @@
return c1;
}
- public static int codePointBefore(byte[] value, int index) {
- char c2 = getChar(value, --index);
+ public static int codePointAt(byte[] value, int index, int end) {
+ return codePointAt(value, index, end, false /* unchecked */);
+ }
+
+ private static int codePointBefore(byte[] value, int index, boolean checked) {
+ --index;
+ if (checked) {
+ checkIndex(index, value);
+ }
+ char c2 = getChar(value, index);
if (Character.isLowSurrogate(c2) && index > 0) {
- char c1 = getChar(value, --index);
+ --index;
+ if (checked) {
+ checkIndex(index, value);
+ }
+ char c1 = getChar(value, index);
if (Character.isHighSurrogate(c1)) {
return Character.toCodePoint(c1, c2);
}
@@ -97,11 +112,19 @@
return c2;
}
- public static int codePointCount(byte[] value, int beginIndex, int endIndex) {
+ public static int codePointBefore(byte[] value, int index) {
+ return codePointBefore(value, index, false /* unchecked */);
+ }
+
+ private static int codePointCount(byte[] value, int beginIndex, int endIndex, boolean checked) {
+ assert beginIndex <= endIndex;
int count = endIndex - beginIndex;
- for (int i = beginIndex; i < endIndex; ) {
+ int i = beginIndex;
+ if (checked && i < endIndex) {
+ checkBoundsBeginEnd(i, endIndex, value);
+ }
+ for (; i < endIndex - 1; ) {
if (Character.isHighSurrogate(getChar(value, i++)) &&
- i < endIndex &&
Character.isLowSurrogate(getChar(value, i))) {
count--;
i++;
@@ -110,6 +133,10 @@
return count;
}
+ public static int codePointCount(byte[] value, int beginIndex, int endIndex) {
+ return codePointCount(value, beginIndex, endIndex, false /* unchecked */);
+ }
+
public static char[] toChars(byte[] value) {
char[] dst = new char[value.length >> 1];
getChars(value, 0, dst.length, dst, 0);
@@ -162,7 +189,7 @@
@HotSpotIntrinsicCandidate
public static int compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
// We need a range check here because 'getChar' has no checks
- checkBoundsOffCount(srcOff << 1, len << 1, src.length);
+ checkBoundsOffCount(srcOff, len, src);
for (int i = 0; i < len; i++) {
char c = getChar(src, srcOff);
if (c > 0xFF) {
@@ -212,7 +239,7 @@
public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) {
// We need a range check here because 'getChar' has no checks
if (srcBegin < srcEnd) {
- checkBoundsOffCount(srcBegin << 1, (srcEnd - srcBegin) << 1, value.length);
+ checkBoundsOffCount(srcBegin, srcEnd - srcBegin, value);
}
for (int i = srcBegin; i < srcEnd; i++) {
dst[dstBegin++] = getChar(value, i);
@@ -319,14 +346,25 @@
if (str.length == 0) {
return 0;
}
- if (value.length == 0) {
+ if (value.length < str.length) {
return -1;
}
- return indexOf(value, length(value), str, length(str), 0);
+ return indexOfUnsafe(value, length(value), str, length(str), 0);
}
@HotSpotIntrinsicCandidate
public static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) {
+ checkBoundsBeginEnd(fromIndex, valueCount, value);
+ checkBoundsBeginEnd(0, strCount, str);
+ return indexOfUnsafe(value, valueCount, str, strCount, fromIndex);
+ }
+
+
+ private static int indexOfUnsafe(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) {
+ assert fromIndex >= 0;
+ assert strCount > 0;
+ assert strCount <= length(str);
+ assert valueCount >= strCount;
char first = getChar(str, 0);
int max = (valueCount - strCount);
for (int i = fromIndex; i <= max; i++) {
@@ -348,6 +386,7 @@
return -1;
}
+
/**
* Handles indexOf Latin1 substring in UTF16 string.
*/
@@ -356,14 +395,24 @@
if (str.length == 0) {
return 0;
}
- if (value.length == 0) {
+ if (length(value) < str.length) {
return -1;
}
- return indexOfLatin1(value, length(value), str, str.length, 0);
+ return indexOfLatin1Unsafe(value, length(value), str, str.length, 0);
}
@HotSpotIntrinsicCandidate
public static int indexOfLatin1(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) {
+ checkBoundsBeginEnd(fromIndex, srcCount, src);
+ String.checkBoundsBeginEnd(0, tgtCount, tgt.length);
+ return indexOfLatin1Unsafe(src, srcCount, tgt, tgtCount, fromIndex);
+ }
+
+ public static int indexOfLatin1Unsafe(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) {
+ assert fromIndex >= 0;
+ assert tgtCount > 0;
+ assert tgtCount <= tgt.length;
+ assert srcCount >= tgtCount;
char first = (char)(tgt[0] & 0xff);
int max = (srcCount - tgtCount);
for (int i = fromIndex; i <= max; i++) {
@@ -389,6 +438,11 @@
@HotSpotIntrinsicCandidate
private static int indexOfChar(byte[] value, int ch, int fromIndex, int max) {
+ checkBoundsBeginEnd(fromIndex, max, value);
+ return indexOfCharUnsafe(value, ch, fromIndex, max);
+ }
+
+ private static int indexOfCharUnsafe(byte[] value, int ch, int fromIndex, int max) {
for (int i = fromIndex; i < max; i++) {
if (getChar(value, i) == ch) {
return i;
@@ -404,6 +458,7 @@
if (Character.isValidCodePoint(ch)) {
final char hi = Character.highSurrogate(ch);
final char lo = Character.lowSurrogate(ch);
+ checkBoundsBeginEnd(fromIndex, max, value);
for (int i = fromIndex; i < max - 1; i++) {
if (getChar(value, i) == hi && getChar(value, i + 1 ) == lo) {
return i;
@@ -413,13 +468,21 @@
return -1;
}
+ // srcCoder == UTF16 && tgtCoder == UTF16
public static int lastIndexOf(byte[] src, int srcCount,
byte[] tgt, int tgtCount, int fromIndex) {
+ assert fromIndex >= 0;
+ assert tgtCount > 0;
+ assert tgtCount <= length(tgt);
int min = tgtCount - 1;
int i = min + fromIndex;
int strLastIndex = tgtCount - 1;
+
+ checkIndex(strLastIndex, tgt);
char strLastChar = getChar(tgt, strLastIndex);
+ checkIndex(i, src);
+
startSearchForLastChar:
while (true) {
while (i >= min && getChar(src, i) != strLastChar) {
@@ -509,6 +572,9 @@
public static boolean regionMatchesCI(byte[] value, int toffset,
byte[] other, int ooffset, int len) {
int last = toffset + len;
+ assert toffset >= 0 && ooffset >= 0;
+ assert ooffset + len <= length(other);
+ assert last <= length(value);
while (toffset < last) {
char c1 = getChar(value, toffset++);
char c2 = getChar(other, ooffset++);
@@ -599,6 +665,8 @@
private static String toLowerCaseEx(String str, byte[] value,
byte[] result, int first, Locale locale,
boolean localeDependent) {
+ assert(result.length == value.length);
+ assert(first >= 0);
int resultOffset = first;
int length = value.length >> 1;
int srcCount;
@@ -633,6 +701,8 @@
System.arraycopy(result, 0, result2, 0, resultOffset << 1);
result = result2;
}
+ assert resultOffset >= 0;
+ assert resultOffset + mapLen <= length(result);
for (int x = 0; x < mapLen; ++x) {
putChar(result, resultOffset++, lowerCharArray[x]);
}
@@ -697,6 +767,8 @@
byte[] result, int first,
Locale locale, boolean localeDependent)
{
+ assert(result.length == value.length);
+ assert(first >= 0);
int resultOffset = first;
int length = value.length >> 1;
int srcCount;
@@ -733,10 +805,12 @@
byte[] result2 = newBytesFor((result.length >> 1) + mapLen - srcCount);
System.arraycopy(result, 0, result2, 0, resultOffset << 1);
result = result2;
- }
- for (int x = 0; x < mapLen; ++x) {
+ }
+ assert resultOffset >= 0;
+ assert resultOffset + mapLen <= length(result);
+ for (int x = 0; x < mapLen; ++x) {
putChar(result, resultOffset++, upperCharArray[x]);
- }
+ }
}
}
return newString(result, 0, resultOffset);
@@ -757,7 +831,7 @@
null;
}
- public static void putChars(byte[] val, int index, char[] str, int off, int end) {
+ private static void putChars(byte[] val, int index, char[] str, int off, int end) {
while (off < end) {
putChar(val, index++, str[off++]);
}
@@ -927,35 +1001,172 @@
////////////////////////////////////////////////////////////////
public static void putCharSB(byte[] val, int index, int c) {
- checkIndex(index, val.length >> 1);
+ checkIndex(index, val);
putChar(val, index, c);
}
public static void putCharsSB(byte[] val, int index, char[] ca, int off, int end) {
- checkOffset(index + end - off, val.length >> 1);
+ checkBoundsBeginEnd(index, index + end - off, val);
putChars(val, index, ca, off, end);
}
public static void putCharsSB(byte[] val, int index, CharSequence s, int off, int end) {
- checkOffset(index + end - off, val.length >> 1);
+ checkBoundsBeginEnd(index, index + end - off, val);
for (int i = off; i < end; i++) {
putChar(val, index++, s.charAt(i));
}
}
public static int codePointAtSB(byte[] val, int index, int end) {
- checkOffset(end, val.length >> 1);
- return codePointAt(val, index, end);
+ return codePointAt(val, index, end, true /* checked */);
}
public static int codePointBeforeSB(byte[] val, int index) {
- checkOffset(index, val.length >> 1);
- return codePointBefore(val, index);
+ return codePointBefore(val, index, true /* checked */);
}
public static int codePointCountSB(byte[] val, int beginIndex, int endIndex) {
- checkOffset(endIndex, val.length >> 1);
- return codePointCount(val, beginIndex, endIndex);
+ return codePointCount(val, beginIndex, endIndex, true /* checked */);
+ }
+
+ public static int getChars(int i, int begin, int end, byte[] value) {
+ checkBoundsBeginEnd(begin, end, value);
+ int pos = getChars(i, end, value);
+ assert begin == pos;
+ return pos;
+ }
+
+ public static int getChars(long l, int begin, int end, byte[] value) {
+ checkBoundsBeginEnd(begin, end, value);
+ int pos = getChars(l, end, value);
+ assert begin == pos;
+ return pos;
+ }
+
+ public static boolean contentEquals(byte[] v1, byte[] v2, int len) {
+ checkBoundsOffCount(0, len, v2);
+ for (int i = 0; i < len; i++) {
+ if ((char)(v1[i] & 0xff) != getChar(v2, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean contentEquals(byte[] value, CharSequence cs, int len) {
+ checkOffset(len, value);
+ for (int i = 0; i < len; i++) {
+ if (getChar(value, i) != cs.charAt(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static int putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4) {
+ int end = i + 4;
+ checkBoundsBeginEnd(i, end, value);
+ putChar(value, i++, c1);
+ putChar(value, i++, c2);
+ putChar(value, i++, c3);
+ putChar(value, i++, c4);
+ assert(i == end);
+ return end;
+ }
+
+ public static int putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4, char c5) {
+ int end = i + 5;
+ checkBoundsBeginEnd(i, end, value);
+ putChar(value, i++, c1);
+ putChar(value, i++, c2);
+ putChar(value, i++, c3);
+ putChar(value, i++, c4);
+ putChar(value, i++, c5);
+ assert(i == end);
+ return end;
+ }
+
+ public static char charAt(byte[] value, int index) {
+ checkIndex(index, value);
+ return getChar(value, index);
+ }
+
+ public static void reverse(byte[] val, int count) {
+ checkOffset(count, val);
+ int n = count - 1;
+ boolean hasSurrogates = false;
+ for (int j = (n-1) >> 1; j >= 0; j--) {
+ int k = n - j;
+ char cj = getChar(val, j);
+ char ck = getChar(val, k);
+ putChar(val, j, ck);
+ putChar(val, k, cj);
+ if (Character.isSurrogate(cj) ||
+ Character.isSurrogate(ck)) {
+ hasSurrogates = true;
+ }
+ }
+ if (hasSurrogates) {
+ reverseAllValidSurrogatePairs(val, count);
+ }
+ }
+
+ /** Outlined helper method for reverse() */
+ private static void reverseAllValidSurrogatePairs(byte[] val, int count) {
+ for (int i = 0; i < count - 1; i++) {
+ char c2 = getChar(val, i);
+ if (Character.isLowSurrogate(c2)) {
+ char c1 = getChar(val, i + 1);
+ if (Character.isHighSurrogate(c1)) {
+ putChar(val, i++, c1);
+ putChar(val, i, c2);
+ }
+ }
+ }
+ }
+
+ // inflatedCopy byte[] -> byte[]
+ public static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
+ // We need a range check here because 'putChar' has no checks
+ checkBoundsOffCount(dstOff, len, dst);
+ for (int i = 0; i < len; i++) {
+ putChar(dst, dstOff++, src[srcOff++] & 0xff);
+ }
+ }
+
+ // srcCoder == UTF16 && tgtCoder == LATIN1
+ public static int lastIndexOfLatin1(byte[] src, int srcCount,
+ byte[] tgt, int tgtCount, int fromIndex) {
+ assert fromIndex >= 0;
+ assert tgtCount > 0;
+ assert tgtCount <= tgt.length;
+ int min = tgtCount - 1;
+ int i = min + fromIndex;
+ int strLastIndex = tgtCount - 1;
+
+ char strLastChar = (char)(tgt[strLastIndex] & 0xff);
+
+ checkIndex(i, src);
+
+ startSearchForLastChar:
+ while (true) {
+ while (i >= min && getChar(src, i) != strLastChar) {
+ i--;
+ }
+ if (i < min) {
+ return -1;
+ }
+ int j = i - 1;
+ int start = j - strLastIndex;
+ int k = strLastIndex - 1;
+ while (j > start) {
+ if (getChar(src, j--) != (tgt[k--] & 0xff)) {
+ i--;
+ continue startSearchForLastChar;
+ }
+ }
+ return start + 1;
+ }
}
////////////////////////////////////////////////////////////////
@@ -975,4 +1186,123 @@
}
static final int MAX_LENGTH = Integer.MAX_VALUE >> 1;
+
+ // Used by trusted callers. Assumes all necessary bounds checks have
+ // been done by the caller.
+
+ /**
+ * This is a variant of {@link Integer#getChars(int, int, byte[])}, but for
+ * UTF-16 coder.
+ *
+ * @param i value to convert
+ * @param index next index, after the least significant digit
+ * @param buf target buffer, UTF16-coded.
+ * @return index of the most significant digit or minus sign, if present
+ */
+ static int getChars(int i, int index, byte[] buf) {
+ int q, r;
+ int charPos = index;
+
+ boolean negative = (i < 0);
+ if (!negative) {
+ i = -i;
+ }
+
+ // Get 2 digits/iteration using ints
+ while (i <= -100) {
+ q = i / 100;
+ r = (q * 100) - i;
+ i = q;
+ putChar(buf, --charPos, Integer.DigitOnes[r]);
+ putChar(buf, --charPos, Integer.DigitTens[r]);
+ }
+
+ // We know there are at most two digits left at this point.
+ q = i / 10;
+ r = (q * 10) - i;
+ putChar(buf, --charPos, '0' + r);
+
+ // Whatever left is the remaining digit.
+ if (q < 0) {
+ putChar(buf, --charPos, '0' - q);
+ }
+
+ if (negative) {
+ putChar(buf, --charPos, '-');
+ }
+ return charPos;
+ }
+
+ /**
+ * This is a variant of {@link Long#getChars(long, int, byte[])}, but for
+ * UTF-16 coder.
+ *
+ * @param i value to convert
+ * @param index next index, after the least significant digit
+ * @param buf target buffer, UTF16-coded.
+ * @return index of the most significant digit or minus sign, if present
+ */
+ static int getChars(long i, int index, byte[] buf) {
+ long q;
+ int r;
+ int charPos = index;
+
+ boolean negative = (i < 0);
+ if (!negative) {
+ i = -i;
+ }
+
+ // Get 2 digits/iteration using longs until quotient fits into an int
+ while (i <= Integer.MIN_VALUE) {
+ q = i / 100;
+ r = (int)((q * 100) - i);
+ i = q;
+ putChar(buf, --charPos, Integer.DigitOnes[r]);
+ putChar(buf, --charPos, Integer.DigitTens[r]);
+ }
+
+ // Get 2 digits/iteration using ints
+ int q2;
+ int i2 = (int)i;
+ while (i2 <= -100) {
+ q2 = i2 / 100;
+ r = (q2 * 100) - i2;
+ i2 = q2;
+ putChar(buf, --charPos, Integer.DigitOnes[r]);
+ putChar(buf, --charPos, Integer.DigitTens[r]);
+ }
+
+ // We know there are at most two digits left at this point.
+ q2 = i2 / 10;
+ r = (q2 * 10) - i2;
+ putChar(buf, --charPos, '0' + r);
+
+ // Whatever left is the remaining digit.
+ if (q2 < 0) {
+ putChar(buf, --charPos, '0' - q2);
+ }
+
+ if (negative) {
+ putChar(buf, --charPos, '-');
+ }
+ return charPos;
+ }
+ // End of trusted methods.
+
+ public static void checkIndex(int off, byte[] val) {
+ String.checkIndex(off, length(val));
+ }
+
+ public static void checkOffset(int off, byte[] val) {
+ String.checkOffset(off, length(val));
+ }
+
+ public static void checkBoundsBeginEnd(int begin, int end, byte[] val) {
+ String.checkBoundsBeginEnd(begin, end, length(val));
+ }
+
+ public static void checkBoundsOffCount(int offset, int count, byte[] val) {
+ String.checkBoundsOffCount(offset, count, length(val));
+ }
+
}
--- a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -617,7 +617,7 @@
}
@Override
- public long getPid() {
+ public long pid() {
return pid;
}
--- a/jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -523,7 +523,7 @@
@Override
public CompletableFuture<Process> onExit() {
- return ProcessHandleImpl.completion(getPid(), false)
+ return ProcessHandleImpl.completion(pid(), false)
.handleAsync((exitStatus, unusedThrowable) -> this);
}
@@ -550,8 +550,8 @@
private static native void terminateProcess(long handle);
@Override
- public long getPid() {
- return processHandle.getPid();
+ public long pid() {
+ return processHandle.pid();
}
private static native int getProcessId0(long handle);
@@ -572,7 +572,7 @@
@Override
public String toString() {
int exitCode = getExitCodeProcess(handle);
- return new StringBuilder("Process[pid=").append(getPid())
+ return new StringBuilder("Process[pid=").append(pid())
.append(", exitValue=").append(exitCode == STILL_ACTIVE ? "\"not exited\"" : exitCode)
.append("]").toString();
}
--- a/jdk/src/java.desktop/share/legal/jpeg.md Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/java.desktop/share/legal/jpeg.md Thu Apr 13 10:01:46 2017 -0700
@@ -1,4 +1,4 @@
-## JPEG release 6b
+## Independent JPEG Group: JPEG release 6b
### JPEG License
<pre>
--- a/jdk/src/jdk.crypto.ec/share/legal/ecc.md Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/jdk.crypto.ec/share/legal/ecc.md Thu Apr 13 10:01:46 2017 -0700
@@ -6,7 +6,8 @@
This notice is provided with respect to Elliptic Curve Cryptography,
which is included with JRE, JDK, and OpenJDK.
-You are receiving a copy of the Elliptic Curve Cryptography library in source
+You are receiving a [copy](http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/tip/src/jdk.crypto.ec/share/native/libsunec/impl)
+of the Elliptic Curve Cryptography library in source
form with the JDK and OpenJDK source distributions, and as object code in
the JRE & JDK runtimes.
--- a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Exchange.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Exchange.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
package jdk.incubator.http;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.net.InetSocketAddress;
import java.net.ProxySelector;
import java.net.SocketPermission;
@@ -64,6 +65,9 @@
final HttpRequestImpl request;
final HttpClientImpl client;
volatile ExchangeImpl<T> exchImpl;
+ // used to record possible cancellation raised before the exchImpl
+ // has been established.
+ private volatile IOException failed;
final List<SocketPermission> permissions = new LinkedList<>();
final AccessControlContext acc;
final MultiExchange<?,T> multi;
@@ -143,14 +147,80 @@
}
public void cancel() {
+ // cancel can be called concurrently before or at the same time
+ // that the exchange impl is being established.
+ // In that case we won't be able to propagate the cancellation
+ // right away
if (exchImpl != null) {
exchImpl.cancel();
+ } else {
+ // no impl - can't cancel impl yet.
+ // call cancel(IOException) instead which takes care
+ // of race conditions between impl/cancel.
+ cancel(new IOException("Request cancelled"));
}
}
public void cancel(IOException cause) {
- if (exchImpl != null) {
- exchImpl.cancel(cause);
+ // If the impl is non null, propagate the exception right away.
+ // Otherwise record it so that it can be propagated once the
+ // exchange impl has been established.
+ ExchangeImpl<?> impl = exchImpl;
+ if (impl != null) {
+ // propagate the exception to the impl
+ impl.cancel(cause);
+ } else {
+ try {
+ // no impl yet. record the exception
+ failed = cause;
+ // now call checkCancelled to recheck the impl.
+ // if the failed state is set and the impl is not null, reset
+ // the failed state and propagate the exception to the impl.
+ checkCancelled(false);
+ } catch (IOException x) {
+ // should not happen - we passed 'false' above
+ throw new UncheckedIOException(x);
+ }
+ }
+ }
+
+ // This method will raise an exception if one was reported and if
+ // it is possible to do so. If the exception can be raised, then
+ // the failed state will be reset. Otherwise, the failed state
+ // will persist until the exception can be raised and the failed state
+ // can be cleared.
+ // Takes care of possible race conditions.
+ private void checkCancelled(boolean throwIfNoImpl) throws IOException {
+ ExchangeImpl<?> impl = null;
+ IOException cause = null;
+ if (failed != null) {
+ synchronized(this) {
+ cause = failed;
+ impl = exchImpl;
+ if (throwIfNoImpl || impl != null) {
+ // The exception will be raised by one of the two methods
+ // below: reset the failed state.
+ failed = null;
+ }
+ }
+ }
+ if (cause == null) return;
+ if (impl != null) {
+ // The exception is raised by propagating it to the impl.
+ impl.cancel(cause);
+ } else if (throwIfNoImpl) {
+ // The exception is raised by throwing it immediately
+ throw cause;
+ } else {
+ Log.logTrace("Exchange: request [{0}/timeout={1}ms] no impl is set."
+ + "\n\tCan''t cancel yet with {2}",
+ request.uri(),
+ request.duration() == null ? -1 :
+ // calling duration.toMillis() can throw an exception.
+ // this is just debugging, we don't care if it overflows.
+ (request.duration().getSeconds() * 1000
+ + request.duration().getNano() / 1000000),
+ cause);
}
}
@@ -191,10 +261,26 @@
}
}
+ // get/set the exchange impl, solving race condition issues with
+ // potential concurrent calls to cancel() or cancel(IOException)
+ private void establishExchange(HttpConnection connection)
+ throws IOException, InterruptedException
+ {
+ // check if we have been cancelled first.
+ checkCancelled(true);
+ // not yet cancelled: create/get a new impl
+ exchImpl = ExchangeImpl.get(this, connection);
+ // recheck for cancelled, in case of race conditions
+ checkCancelled(true);
+ // now we're good to go. because exchImpl is no longer null
+ // cancel() will be able to propagate directly to the impl
+ // after this point.
+ }
+
private Response responseImpl0(HttpConnection connection)
throws IOException, InterruptedException
{
- exchImpl = ExchangeImpl.get(this, connection);
+ establishExchange(connection);
exchImpl.setClientForRequest(requestProcessor);
if (request.expectContinue()) {
Log.logTrace("Sending Expect: 100-Continue");
@@ -257,7 +343,7 @@
CompletableFuture<Response> responseAsyncImpl0(HttpConnection connection) {
try {
- exchImpl = ExchangeImpl.get(this, connection);
+ establishExchange(connection);
} catch (IOException | InterruptedException e) {
return MinimalFuture.failedFuture(e);
}
--- a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Http1Exchange.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Http1Exchange.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,9 +46,12 @@
class Http1Exchange<T> extends ExchangeImpl<T> {
final HttpRequestImpl request; // main request
- final List<CompletableFuture<?>> operations; // used for cancel
+ private final List<CompletableFuture<?>> operations; // used for cancel
final Http1Request requestAction;
- volatile Http1Response<T> response;
+ private volatile Http1Response<T> response;
+ // use to record possible cancellation raised before any operation
+ // has been initiated.
+ private IOException failed;
final HttpConnection connection;
final HttpClientImpl client;
final Executor executor;
@@ -70,7 +73,7 @@
this.request = exchange.request();
this.client = exchange.client();
this.executor = exchange.executor();
- this.operations = Collections.synchronizedList(new LinkedList<>());
+ this.operations = new LinkedList<>();
this.buffer = exchange.getBuffer();
if (connection != null) {
this.connection = connection;
@@ -186,9 +189,22 @@
}
connection.close();
int count = 0;
- for (CompletableFuture<?> cf : operations) {
- cf.completeExceptionally(cause);
- count++;
+ if (operations.isEmpty()) {
+ failed = cause;
+ Log.logTrace("Http1Exchange: request [{0}/timeout={1}ms] no pending operation."
+ + "\n\tCan''t cancel yet with {2}",
+ request.uri(),
+ request.duration() == null ? -1 :
+ // calling duration.toMillis() can throw an exception.
+ // this is just debugging, we don't care if it overflows.
+ (request.duration().getSeconds() * 1000
+ + request.duration().getNano() / 1000000),
+ cause);
+ } else {
+ for (CompletableFuture<?> cf : operations) {
+ cf.completeExceptionally(cause);
+ count++;
+ }
}
Log.logError("Http1Exchange.cancel: count=" + count);
}
@@ -206,8 +222,24 @@
CompletableFuture<Response> cf =
connection.whenReceivingResponse()
.thenCompose((v) -> getResponseAsyncImpl(executor));
-
- operations.add(cf);
+ IOException cause;
+ synchronized(this) {
+ operations.add(cf);
+ cause = failed;
+ failed = null;
+ }
+ if (cause != null) {
+ Log.logTrace("Http1Exchange: request [{0}/timeout={1}ms]"
+ + "\n\tCompleting exceptionally with {2}\n",
+ request.uri(),
+ request.duration() == null ? -1 :
+ // calling duration.toMillis() can throw an exception.
+ // this is just debugging, we don't care if it overflows.
+ (request.duration().getSeconds() * 1000
+ + request.duration().getNano() / 1000000),
+ cause);
+ cf.completeExceptionally(cause);
+ }
return cf;
}
}
--- a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpClientImpl.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpClientImpl.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -582,12 +582,14 @@
// Timers are implemented through timed Selector.select() calls.
synchronized void registerTimer(TimeoutEvent event) {
+ Log.logTrace("Registering timer {0}", event);
timeouts.add(event);
selmgr.wakeupSelector();
}
synchronized void cancelTimer(TimeoutEvent event) {
- timeouts.stream().filter(e -> e == event).forEach(timeouts::remove);
+ Log.logTrace("Canceling timer {0}", event);
+ timeouts.remove(event);
}
/**
@@ -595,23 +597,61 @@
* returns the amount of time, in milliseconds, until the next earliest
* event. A return value of 0 means that there are no events.
*/
- private synchronized long purgeTimeoutsAndReturnNextDeadline() {
- if (timeouts.isEmpty())
- return 0L;
+ private long purgeTimeoutsAndReturnNextDeadline() {
+ long diff = 0L;
+ List<TimeoutEvent> toHandle = null;
+ int remaining = 0;
+ // enter critical section to retrieve the timeout event to handle
+ synchronized(this) {
+ if (timeouts.isEmpty()) return 0L;
+
+ Instant now = Instant.now();
+ Iterator<TimeoutEvent> itr = timeouts.iterator();
+ while (itr.hasNext()) {
+ TimeoutEvent event = itr.next();
+ diff = now.until(event.deadline(), ChronoUnit.MILLIS);
+ if (diff <= 0) {
+ itr.remove();
+ toHandle = (toHandle == null) ? new ArrayList<>() : toHandle;
+ toHandle.add(event);
+ } else {
+ break;
+ }
+ }
+ remaining = timeouts.size();
+ }
- Instant now = Instant.now();
- Iterator<TimeoutEvent> itr = timeouts.iterator();
- while (itr.hasNext()) {
- TimeoutEvent event = itr.next();
- long diff = now.until(event.deadline(), ChronoUnit.MILLIS);
- if (diff <= 0) {
- itr.remove();
- event.handle(); // TODO: release lock.
- } else {
- return diff;
+ // can be useful for debugging
+ if (toHandle != null && Log.trace()) {
+ Log.logTrace("purgeTimeoutsAndReturnNextDeadline: handling "
+ + (toHandle == null ? 0 : toHandle.size()) + " events, "
+ + "remaining " + remaining
+ + ", next deadline: " + (diff < 0 ? 0L : diff));
+ }
+
+ // handle timeout events out of critical section
+ if (toHandle != null) {
+ Throwable failed = null;
+ for (TimeoutEvent event : toHandle) {
+ try {
+ Log.logTrace("Firing timer {0}", event);
+ event.handle();
+ } catch (Error | RuntimeException e) {
+ // Not expected. Handle remaining events then throw...
+ // If e is an OOME or SOE it might simply trigger a new
+ // error from here - but in this case there's not much we
+ // could do anyway. Just let it flow...
+ if (failed == null) failed = e;
+ else failed.addSuppressed(e);
+ Log.logTrace("Failed to handle event {0}: {1}", event, e);
+ }
}
+ if (failed instanceof Error) throw (Error) failed;
+ if (failed instanceof RuntimeException) throw (RuntimeException) failed;
}
- return 0L;
+
+ // return time to wait until next event. 0L if there's no more events.
+ return diff < 0 ? 0L : diff;
}
// used for the connection window
--- a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/MultiExchange.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/MultiExchange.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -357,9 +357,5 @@
public void handle() {
cancel(new HttpTimeoutException("request timed out"));
}
- @Override
- public String toString() {
- return "[deadline = " + deadline() + "]";
- }
}
}
--- a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/PlainHttpConnection.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/PlainHttpConnection.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -54,7 +54,7 @@
*/
class PlainHttpConnection extends HttpConnection implements AsyncConnection {
- protected SocketChannel chan;
+ protected final SocketChannel chan;
private volatile boolean connected;
private boolean closed;
@@ -100,6 +100,7 @@
chan.finishConnect();
} catch (IOException e) {
cf.completeExceptionally(e);
+ return;
}
connected = true;
cf.complete(null);
--- a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Stream.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Stream.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -670,11 +670,21 @@
@Override
CompletableFuture<Response> getResponseAsync(Executor executor) {
- CompletableFuture<Response> cf;
+ CompletableFuture<Response> cf = null;
+ // The code below deals with race condition that can be caused when
+ // completeResponse() is being called before getResponseAsync()
synchronized (response_cfs) {
if (!response_cfs.isEmpty()) {
+ // This CompletableFuture was created by completeResponse().
+ // it will be already completed.
cf = response_cfs.remove(0);
+ // if we find a cf here it should be already completed.
+ // finding a non completed cf should not happen. just assert it.
+ assert cf.isDone() : "Removing uncompleted response: could cause code to hang!";
} else {
+ // getResponseAsync() is called first. Create a CompletableFuture
+ // that will be completed by completeResponse() when
+ // completeResponse() is called.
cf = new MinimalFuture<>();
response_cfs.add(cf);
}
@@ -708,7 +718,7 @@
cf.complete(resp);
response_cfs.remove(cf);
return;
- }
+ } // else we found the previous response: just leave it alone.
}
cf = MinimalFuture.completedFuture(resp);
Log.logTrace("Created completed future (streamid={0}): {1}",
@@ -742,10 +752,13 @@
*/
void completeResponseExceptionally(Throwable t) {
synchronized (response_cfs) {
- for (CompletableFuture<Response> cf : response_cfs) {
+ // use index to avoid ConcurrentModificationException
+ // caused by removing the CF from within the loop.
+ for (int i = 0; i < response_cfs.size(); i++) {
+ CompletableFuture<Response> cf = response_cfs.get(i);
if (!cf.isDone()) {
cf.completeExceptionally(t);
- response_cfs.remove(cf);
+ response_cfs.remove(i);
return;
}
}
--- a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/TimeoutEvent.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/TimeoutEvent.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,10 +27,11 @@
import java.time.Duration;
import java.time.Instant;
+import java.util.concurrent.atomic.AtomicLong;
/**
* Timeout event notified by selector thread. Executes the given handler if
- * the timer not cancelled first.
+ * the timer not canceled first.
*
* Register with {@link HttpClientImpl#registerTimer(TimeoutEvent)}.
*
@@ -38,6 +39,10 @@
*/
abstract class TimeoutEvent implements Comparable<TimeoutEvent> {
+ private static final AtomicLong COUNTER = new AtomicLong();
+ // we use id in compareTo to make compareTo consistent with equals
+ // see TimeoutEvent::compareTo below;
+ private final long id = COUNTER.incrementAndGet();
private final Instant deadline;
TimeoutEvent(Duration duration) {
@@ -52,6 +57,24 @@
@Override
public int compareTo(TimeoutEvent other) {
- return this.deadline.compareTo(other.deadline);
+ if (other == this) return 0;
+ // if two events have the same deadline, but are not equals, then the
+ // smaller is the one that was created before (has the smaller id).
+ // This is arbitrary and we don't really care which is smaller or
+ // greater, but we need a total order, so two events with the
+ // same deadline cannot compare == 0 if they are not equals.
+ final int compareDeadline = this.deadline.compareTo(other.deadline);
+ if (compareDeadline == 0 && !this.equals(other)) {
+ long diff = this.id - other.id; // should take care of wrap around
+ if (diff < 0) return -1;
+ else if (diff > 0) return 1;
+ else assert false : "Different events with same id and deadline";
+ }
+ return compareDeadline;
+ }
+
+ @Override
+ public String toString() {
+ return "TimeoutEvent[id=" + id + ", deadline=" + deadline + "]";
}
}
--- a/jdk/src/jdk.management/share/classes/com/sun/management/VMOption.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/src/jdk.management/share/classes/com/sun/management/VMOption.java Thu Apr 13 10:01:46 2017 -0700
@@ -47,8 +47,6 @@
* object was constructed. The value of the VM option
* may be changed after the {@code VMOption} object was constructed,
*
- * @see <a href="{@docRoot}/../../../../technotes/guides/vm/index.html">
- * Java Virtual Machine</a>
* @author Mandy Chung
* @since 1.6
*/
--- a/jdk/test/ProblemList.txt Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/ProblemList.txt Thu Apr 13 10:01:46 2017 -0700
@@ -170,8 +170,6 @@
java/net/DatagramSocket/SendDatagramToBadAddress.java 7143960 macosx-all
-java/net/httpclient/TimeoutOrdering.java 8170940 solaris-all,windows-all
-
############################################################################
# jdk_nio
--- a/jdk/test/com/sun/jdi/ProcessAttachTest.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/com/sun/jdi/ProcessAttachTest.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,13 +23,11 @@
import java.io.IOException;
import java.io.InputStream;
-import java.util.List;
import java.util.Map;
import jdk.testlibrary.ProcessTools;
import com.sun.jdi.Bootstrap;
-import com.sun.jdi.ThreadReference;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.connect.AttachingConnector;
import com.sun.jdi.connect.Connector;
@@ -86,7 +84,7 @@
is.read();
// Attach a debugger
- tryDebug(p.getPid());
+ tryDebug(p.pid());
} finally {
p.destroyForcibly();
}
--- a/jdk/test/java/io/FilePermission/Correctness.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/java/io/FilePermission/Correctness.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -89,12 +89,14 @@
//check("/-", "-");
try {
- // containsPath is broken on Windows.
containsMethod = FilePermission.class.getDeclaredMethod(
"containsPath", Path.class, Path.class);
containsMethod.setAccessible(true);
System.out.println();
+ // The 1st 2 args of contains() must be normalized paths.
+ // When FilePermission::containsPath is called by implies,
+ // paths have already been normalized.
contains("x", "x", 0);
contains("x", "x/y", 1);
contains("x", "x/y/z", 2);
@@ -160,7 +162,7 @@
}
}
- static void check(String s1, String s2, boolean expected) {
+ static void check0(String s1, String s2, boolean expected) {
FilePermission fp1 = new FilePermission(s1, "read");
FilePermission fp2 = new FilePermission(s2, "read");
boolean b = fp1.implies(fp2);
@@ -173,6 +175,16 @@
}
}
+ static void check(String s1, String s2, boolean expected) {
+ check0(s1, s2, expected);
+ if (isWindows) {
+ check0("C:" + s1, s2, false);
+ check0(s1, "C:" + s2, false);
+ check0("C:" + s1, "D:" + s2, false);
+ check0("C:" + s1, "C:" + s2, expected);
+ }
+ }
+
static void check(String s1, String s2) {
check(s1, s2, true);
}
--- a/jdk/test/java/lang/ProcessBuilder/Basic.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/java/lang/ProcessBuilder/Basic.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -311,7 +311,7 @@
if (action.equals("sleep")) {
Thread.sleep(10 * 60 * 1000L);
} else if (action.equals("pid")) {
- System.out.println(ProcessHandle.current().getPid());
+ System.out.println(ProcessHandle.current().pid());
} else if (action.equals("testIO")) {
String expected = "standard input";
char[] buf = new char[expected.length()+1];
@@ -1235,7 +1235,7 @@
Process p = pb.start();
String s = commandOutput(p);
long actualPid = Long.valueOf(s.trim());
- long expectedPid = p.getPid();
+ long expectedPid = p.pid();
equal(actualPid, expectedPid);
} catch (Throwable t) {
unexpected(t);
@@ -1245,7 +1245,7 @@
// Test the default implementation of Process.getPid
DelegatingProcess p = new DelegatingProcess(null);
THROWS(UnsupportedOperationException.class,
- () -> p.getPid(),
+ () -> p.pid(),
() -> p.toHandle(),
() -> p.supportsNormalTermination(),
() -> p.children(),
@@ -2243,7 +2243,7 @@
// Child process waits until it gets input
String s = p.toString();
check(s.contains("not exited"));
- check(s.contains("pid=" + p.getPid() + ","));
+ check(s.contains("pid=" + p.pid() + ","));
new PrintStream(p.getOutputStream()).print("standard input");
p.getOutputStream().close();
@@ -2251,7 +2251,7 @@
// Check the toString after it exits
int exitValue = p.waitFor();
s = p.toString();
- check(s.contains("pid=" + p.getPid() + ","));
+ check(s.contains("pid=" + p.pid() + ","));
check(s.contains("exitValue=" + exitValue) &&
!s.contains("not exited"));
}
--- a/jdk/test/java/lang/ProcessBuilder/PipelineTest.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/java/lang/ProcessBuilder/PipelineTest.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -212,7 +212,7 @@
static void print(ProcessHandle p) {
System.out.printf("process: pid: %d, info: %s%n",
- p.getPid(), p.info());
+ p.pid(), p.info());
}
// Check various aspects of the processes
--- a/jdk/test/java/lang/ProcessBuilder/Zombies.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/java/lang/ProcessBuilder/Zombies.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,7 @@
! new File("/bin/ps").canExecute())
return;
System.out.println("Looks like a Unix system.");
- long mypid = ProcessHandle.current().getPid();
+ long mypid = ProcessHandle.current().pid();
System.out.printf("mypid: %d%n", mypid);
final Runtime rt = Runtime.getRuntime();
@@ -65,7 +65,7 @@
Process p = rt.exec(TrueCommand);
ProcessHandle pp = p.toHandle().parent().orElse(null);
- System.out.printf("%s pid: %d, parent: %s%n", TrueCommand, p.getPid(), pp);
+ System.out.printf("%s pid: %d, parent: %s%n", TrueCommand, p.pid(), pp);
p.waitFor();
// Count all the zombies that are children of this Java process
--- a/jdk/test/java/lang/ProcessHandle/Basic.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/java/lang/ProcessHandle/Basic.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -66,13 +66,13 @@
public static void test2() {
try {
ProcessHandle self = ProcessHandle.current();
- long pid = self.getPid(); // known native process id
+ long pid = self.pid(); // known native process id
Optional<ProcessHandle> self1 = ProcessHandle.of(pid);
assertEquals(self1.get(), self,
- "ProcessHandle.of(x.getPid()) should be equal getPid() %d: %d");
+ "ProcessHandle.of(x.pid()) should be equal pid() %d: %d");
Optional<ProcessHandle> ph = ProcessHandle.of(pid);
- assertEquals(pid, ph.get().getPid());
+ assertEquals(pid, ph.get().pid());
} finally {
// Cleanup any left over processes
ProcessHandle.current().children().forEach(ProcessHandle::destroy);
@@ -98,7 +98,7 @@
Process p = new ProcessBuilder("sleep", "0").start();
p.waitFor();
- long deadPid = p.getPid();
+ long deadPid = p.pid();
p = null; // Forget the process
Optional<ProcessHandle> t = ProcessHandle.of(deadPid);
--- a/jdk/test/java/lang/ProcessHandle/JavaChild.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/java/lang/ProcessHandle/JavaChild.java Thu Apr 13 10:01:46 2017 -0700
@@ -159,7 +159,7 @@
*/
CompletableFuture<String> forEachOutputLine(Consumer<String> consumer) {
final CompletableFuture<String> future = new CompletableFuture<>();
- String name = "OutputLineReader-" + getPid();
+ String name = "OutputLineReader-" + pid();
Thread t = new Thread(() -> {
try (BufferedReader reader = outputReader()) {
String line;
@@ -167,7 +167,7 @@
consumer.accept(line);
}
} catch (IOException | RuntimeException ex) {
- consumer.accept("IOE (" + getPid() + "):" + ex.getMessage());
+ consumer.accept("IOE (" + pid() + "):" + ex.getMessage());
future.completeExceptionally(ex);
}
future.complete("success");
@@ -327,7 +327,7 @@
try {
p.getOutputStream().close();
} catch (IOException ie) {
- sendResult("stdin_closing", p.getPid(),
+ sendResult("stdin_closing", p.pid(),
"exception", ie.getMessage());
}
}
@@ -352,9 +352,9 @@
"children to terminate%n");
children.removeAll(completedChildren);
for (JavaChild c : children) {
- sendResult("stdin_noterm", c.getPid());
+ sendResult("stdin_noterm", c.pid());
System.err.printf(" Process not terminated: " +
- "pid: %d%n", c.getPid());
+ "pid: %d%n", c.pid());
}
System.exit(2);
}
@@ -386,11 +386,11 @@
System.arraycopy(args, nextArg, subargs, 0, subargs.length);
for (int i = 0; i < ncount; i++) {
JavaChild p = spawnJavaChild(subargs);
- sendResult(action, p.getPid());
+ sendResult(action, p.pid());
p.forEachOutputLine(JavaChild::sendRaw);
p.onJavaChildExit().thenAccept((p1) -> {
int excode = p1.exitValue();
- sendResult("child_exit", p1.getPid(), excode);
+ sendResult("child_exit", p1.pid(), excode);
completedChildren.add(p1);
});
children.add(p); // Add child to spawned list
@@ -410,7 +410,7 @@
if (p.isAlive()) {
sentCount++;
// overwrite with current pid
- result[0] = Long.toString(p.getPid());
+ result[0] = Long.toString(p.pid());
sendResult(action, result);
p.sendAction(args[nextArg], subargs);
}
@@ -426,7 +426,7 @@
// ignoring those that are not alive
for (JavaChild p : children) {
if (p.isAlive()) {
- sendResult(action, p.getPid());
+ sendResult(action, p.pid());
p.getOutputStream().close();
}
}
@@ -505,7 +505,7 @@
String command;
Object[] results;
Event(String command, Object... results) {
- this(self.getPid(), ++commandSeq, command, results);
+ this(self.pid(), ++commandSeq, command, results);
}
Event(long pid, int seq, String command, Object... results) {
this.pid = pid;
--- a/jdk/test/java/lang/ProcessHandle/OnExitTest.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/java/lang/ProcessHandle/OnExitTest.java Thu Apr 13 10:01:46 2017 -0700
@@ -104,7 +104,7 @@
JavaChild proc = JavaChild.spawnJavaChild("stdin");
procHandle = proc.toHandle();
- printf(" spawned: %d%n", proc.getPid());
+ printf(" spawned: %d%n", proc.pid());
proc.forEachOutputLine((s) -> {
String[] split = s.trim().split(" ");
@@ -235,7 +235,7 @@
} while (!"pid".equals(split[1]));
// Tell B to wait for A's pid
- B.sendAction("waitpid", A.getPid());
+ B.sendAction("waitpid", A.pid());
// Wait a bit to see if B will prematurely report the termination of A
try {
--- a/jdk/test/java/lang/ProcessHandle/ProcessUtil.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/java/lang/ProcessHandle/ProcessUtil.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -199,7 +199,7 @@
*/
static void printProcess(ProcessHandle ph, String prefix) {
printf("%spid %s, alive: %s; parent: %s, %s%n", prefix,
- ph.getPid(), ph.isAlive(), ph.parent(), ph.info());
+ ph.pid(), ph.isAlive(), ph.parent(), ph.info());
}
/**
--- a/jdk/test/java/lang/ProcessHandle/TreeTest.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/java/lang/ProcessHandle/TreeTest.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -73,7 +73,7 @@
try {
ProcessHandle self = ProcessHandle.current();
- printf("self pid: %d%n", self.getPid());
+ printf("self pid: %d%n", self.pid());
printDeep(self, "");
for (int i = 0; i < MAXCHILDREN; i++) {
@@ -154,7 +154,7 @@
JavaChild p1 = JavaChild.spawnJavaChild("stdin");
ProcessHandle p1Handle = p1.toHandle();
- printf(" p1 pid: %d%n", p1.getPid());
+ printf(" p1 pid: %d%n", p1.pid());
// Gather the PIDs from the output of the spawing process
p1.forEachOutputLine((s) -> {
@@ -206,7 +206,7 @@
// show the complete list of children (for debug)
List<ProcessHandle> descendants = getDescendants(p1Handle);
printf(" descendants: %s%n",
- descendants.stream().map(p -> p.getPid())
+ descendants.stream().map(p -> p.pid())
.collect(Collectors.toList()));
// Verify that all spawned children show up in the descendants List
@@ -252,7 +252,7 @@
JavaChild p1 = JavaChild.spawnJavaChild("stdin");
ProcessHandle p1Handle = p1.toHandle();
- printf(" p1: %s%n", p1.getPid());
+ printf(" p1: %s%n", p1.pid());
int newChildren = 3;
CountDownLatch spawnCount = new CountDownLatch(newChildren);
@@ -356,11 +356,11 @@
parent[sortindex[i]] = processes[sortindex[i]].parent().orElse(null);
}
Arrays.sort(sortindex, (i1, i2) -> {
- int cmp = Long.compare((parent[i1] == null ? 0L : parent[i1].getPid()),
- (parent[i2] == null ? 0L : parent[i2].getPid()));
+ int cmp = Long.compare((parent[i1] == null ? 0L : parent[i1].pid()),
+ (parent[i2] == null ? 0L : parent[i2].pid()));
if (cmp == 0) {
- cmp = Long.compare((processes[i1] == null ? 0L : processes[i1].getPid()),
- (processes[i2] == null ? 0L : processes[i2].getPid()));
+ cmp = Long.compare((processes[i1] == null ? 0L : processes[i1].pid()),
+ (processes[i2] == null ? 0L : processes[i2].pid()));
}
return cmp;
});
@@ -397,7 +397,7 @@
ProcessHandle p1Handle = p1.toHandle();
printf("Spawning %d x %d x %d processes, pid: %d%n",
- factor, factor, factor, p1.getPid());
+ factor, factor, factor, p1.pid());
// Start the first tier of subprocesses
p1.sendAction("spawn", factor, "stdin");
@@ -448,7 +448,7 @@
List<ProcessHandle> subprocesses = getDescendants(p1Handle);
printf(" descendants: %s%n",
- subprocesses.stream().map(p -> p.getPid())
+ subprocesses.stream().map(p -> p.pid())
.collect(Collectors.toList()));
p1.getOutputStream().close(); // Close stdin for the controlling p1
--- a/jdk/test/java/lang/Runtime/exec/SleepyCat.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/java/lang/Runtime/exec/SleepyCat.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -80,10 +80,10 @@
for (Process p : pids) {
if (p == null)
continue;
- String[] pfiles = {"pfiles", Long.toString(p.getPid())};
+ String[] pfiles = {"pfiles", Long.toString(p.pid())};
fds = new ProcessBuilder(pfiles).inheritIO().start();
fds.waitFor();
- String[] pstack = {"pstack", Long.toString(p.getPid())};
+ String[] pstack = {"pstack", Long.toString(p.pid())};
fds = new ProcessBuilder(pstack).inheritIO().start();
fds.waitFor();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/SmallTimeout.java Thu Apr 13 10:01:46 2017 -0700
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.URI;
+import jdk.incubator.http.HttpClient;
+import jdk.incubator.http.HttpRequest;
+import jdk.incubator.http.HttpResponse;
+import jdk.incubator.http.HttpTimeoutException;
+import java.time.Duration;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import static java.lang.System.out;
+import static jdk.incubator.http.HttpResponse.BodyHandler.discard;
+
+/**
+ * @test
+ * @bug 8178147
+ * @summary Ensures that small timeouts do not cause hangs due to race conditions
+ * @run main/othervm SmallTimeout
+ */
+
+// To enable logging use. Not enabled by default as it changes the dynamics
+// of the test.
+// @run main/othervm -Djdk.httpclient.HttpClient.log=all,frames:all SmallTimeout
+
+public class SmallTimeout {
+
+ static int[] TIMEOUTS = {2, 1, 3, 2, 100, 1};
+
+ // A queue for placing timed out requests so that their order can be checked.
+ static LinkedBlockingQueue<HttpRequest> queue = new LinkedBlockingQueue<>();
+
+ static volatile boolean error;
+
+ public static void main(String[] args) throws Exception {
+ HttpClient client = HttpClient.newHttpClient();
+
+ try (ServerSocket ss = new ServerSocket(0, 20)) {
+ int port = ss.getLocalPort();
+ URI uri = new URI("http://127.0.0.1:" + port + "/");
+
+ HttpRequest[] requests = new HttpRequest[TIMEOUTS.length];
+
+ out.println("--- TESTING Async");
+ for (int i = 0; i < TIMEOUTS.length; i++) {
+ requests[i] = HttpRequest.newBuilder(uri)
+ .timeout(Duration.ofMillis(TIMEOUTS[i]))
+ .GET()
+ .build();
+
+ final HttpRequest req = requests[i];
+ CompletableFuture<HttpResponse<Object>> response = client
+ .sendAsync(req, discard(null))
+ .whenComplete((HttpResponse<Object> r, Throwable t) -> {
+ if (r != null) {
+ out.println("Unexpected response: " + r);
+ error = true;
+ }
+ if (t != null) {
+ if (!(t.getCause() instanceof HttpTimeoutException)) {
+ out.println("Wrong exception type:" + t.toString());
+ Throwable c = t.getCause() == null ? t : t.getCause();
+ c.printStackTrace();
+ error = true;
+ } else {
+ out.println("Caught expected timeout: " + t.getCause());
+ }
+ }
+ if (t == null && r == null) {
+ out.println("Both response and throwable are null!");
+ error = true;
+ }
+ queue.add(req);
+ });
+ }
+ System.out.println("All requests submitted. Waiting ...");
+
+ checkReturn(requests);
+
+ if (error)
+ throw new RuntimeException("Failed. Check output");
+
+ // Repeat blocking in separate threads. Use queue to wait.
+ out.println("--- TESTING Sync");
+
+ // For running blocking response tasks
+ ExecutorService executor = Executors.newCachedThreadPool();
+
+ for (int i = 0; i < TIMEOUTS.length; i++) {
+ requests[i] = HttpRequest.newBuilder(uri)
+ .timeout(Duration.ofMillis(TIMEOUTS[i]))
+ .GET()
+ .build();
+
+ final HttpRequest req = requests[i];
+ executor.execute(() -> {
+ try {
+ client.send(req, discard(null));
+ } catch (HttpTimeoutException e) {
+ out.println("Caught expected timeout: " + e);
+ queue.offer(req);
+ } catch (IOException | InterruptedException ee) {
+ Throwable c = ee.getCause() == null ? ee : ee.getCause();
+ c.printStackTrace();
+ error = true;
+ }
+ });
+ }
+ System.out.println("All requests submitted. Waiting ...");
+
+ checkReturn(requests);
+
+ executor.shutdownNow();
+
+ if (error)
+ throw new RuntimeException("Failed. Check output");
+
+ } finally {
+ ((ExecutorService) client.executor()).shutdownNow();
+ }
+ }
+
+ static void checkReturn(HttpRequest[] requests) throws InterruptedException {
+ // wait for exceptions and check order
+ for (int j = 0; j < TIMEOUTS.length; j++) {
+ HttpRequest req = queue.take();
+ out.println("Got request from queue " + req + ", order: " + getRequest(req, requests));
+ }
+ out.println("Return ok");
+ }
+
+ /** Returns the index of the request in the array. */
+ static String getRequest(HttpRequest req, HttpRequest[] requests) {
+ for (int i=0; i<requests.length; i++) {
+ if (req == requests[i]) {
+ return "r" + i;
+ }
+ }
+ throw new AssertionError("Unknown request: " + req);
+ }
+}
--- a/jdk/test/java/net/httpclient/TimeoutOrdering.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/java/net/httpclient/TimeoutOrdering.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,6 +43,9 @@
* @run main/othervm TimeoutOrdering
*/
+// To enable logging use
+// @run main/othervm -Djdk.httpclient.HttpClient.log=all,frames:all TimeoutOrdering
+
public class TimeoutOrdering {
// The assumption is that 5 secs is sufficiently large enough, without being
@@ -81,6 +84,8 @@
if (t != null) {
if (!(t.getCause() instanceof HttpTimeoutException)) {
out.println("Wrong exception type:" + t.toString());
+ Throwable c = t.getCause() == null ? t : t.getCause();
+ c.printStackTrace();
error = true;
} else {
out.println("Caught expected timeout: " + t.getCause());
@@ -116,6 +121,8 @@
out.println("Caught expected timeout: " + e);
queue.offer(req);
} catch (IOException | InterruptedException ee) {
+ Throwable c = ee.getCause() == null ? ee : ee.getCause();
+ c.printStackTrace();
error = true;
}
});
--- a/jdk/test/java/util/logging/LoggingDeadlock2.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/java/util/logging/LoggingDeadlock2.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -263,7 +263,7 @@
sleep(ms);
System.err.println("Timeout reached: " + ms);
if (process.isAlive()) {
- long pid = process.getPid();
+ long pid = process.pid();
ProcessBuilder jstack = new ProcessBuilder(jstackExe, String.valueOf(pid));
System.err.println("Dumping subprocess stack: " + pid);
Process p = jstack.inheritIO().start();
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessThread.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessThread.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
import java.io.PrintWriter;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
/**
@@ -195,7 +194,7 @@
* @return The PID associated with this process runnable
*/
public long getPid() throws InterruptedException {
- return getProcess().getPid();
+ return getProcess().pid();
}
public void sendMessage(String message) throws InterruptedException {
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -256,7 +256,7 @@
* @return Process id
*/
public static long getProcessId() {
- return ProcessHandle.current().getPid();
+ return ProcessHandle.current().pid();
}
/**
@@ -542,8 +542,8 @@
}
@Override
- public long getPid() {
- return p.getPid();
+ public long pid() {
+ return p.pid();
}
@Override
--- a/jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -144,7 +144,7 @@
System.out.println("Attaching test manager:");
System.out.println("=========================");
- System.out.println(" PID : " + serverPrc.getPid());
+ System.out.println(" PID : " + serverPrc.pid());
System.out.println(" shutdown port : " + port.get());
ProcessBuilder client = ProcessTools.createJavaProcessBuilder(
@@ -152,7 +152,7 @@
TEST_CLASSPATH,
"--add-exports", "jdk.management.agent/jdk.internal.agent=ALL-UNNAMED",
"TestManager",
- String.valueOf(serverPrc.getPid()),
+ String.valueOf(serverPrc.pid()),
port.get(),
"true"
);
--- a/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -129,7 +129,7 @@
System.out.println("Attaching test manager:");
System.out.println("=========================");
- System.out.println(" PID : " + serverPrc.getPid());
+ System.out.println(" PID : " + serverPrc.pid());
System.out.println(" shutdown port : " + port.get());
ProcessBuilder client = ProcessTools.createJavaProcessBuilder(
@@ -137,7 +137,7 @@
TEST_CLASSPATH,
"--add-exports", "jdk.management.agent/jdk.internal.agent=ALL-UNNAMED",
"TestManager",
- String.valueOf(serverPrc.getPid()),
+ String.valueOf(serverPrc.pid()),
port.get(),
"true"
);
--- a/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -346,7 +346,7 @@
throw new BindException("Starting process failed due to " +
"the requested port not being available");
}
- pid = p.getPid();
+ pid = p.pid();
} catch (TimeoutException e) {
if (p != null) {
p.destroy();
--- a/jdk/test/sun/tools/jps/LingeredApp.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/sun/tools/jps/LingeredApp.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -141,7 +141,7 @@
if (appProcess == null) {
throw new RuntimeException("Process is not alive");
}
- return appProcess.getPid();
+ return appProcess.pid();
}
/**
--- a/jdk/test/sun/tools/jstat/JStatInterval.java Tue Apr 11 00:05:00 2017 +0300
+++ b/jdk/test/sun/tools/jstat/JStatInterval.java Thu Apr 13 10:01:46 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,11 +36,8 @@
import jdk.testlibrary.ProcessTools;
import jdk.testlibrary.JDKToolLauncher;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
public class JStatInterval {
private static final String READY = "READY";
@@ -88,7 +85,7 @@
throw new Error("Unable to start the monitored application.");
}
- String pidStr = String.valueOf(app.getPid());
+ String pidStr = String.valueOf(app.pid());
JDKToolLauncher l = JDKToolLauncher.createUsingTestJDK("jstat");
l.addToolArg("-compiler");
l.addToolArg(pidStr);