This commit is contained in:
Phil Race 2017-04-13 10:57:40 -07:00
commit 97300d43cd
48 changed files with 1042 additions and 504 deletions

View File

@ -407,3 +407,4 @@ cac788454598b95d8b0153c021a7fae3cd7e6fda jdk-9+160
f6bf027e88e9a4dd19f721001a7af00157af42c4 jdk-9+162 f6bf027e88e9a4dd19f721001a7af00157af42c4 jdk-9+162
50171f8c47961710cbf87aead6f03fa431d8d240 jdk-9+163 50171f8c47961710cbf87aead6f03fa431d8d240 jdk-9+163
6dea581453d7c0e767e3169cfec8b423a381e71d jdk-9+164 6dea581453d7c0e767e3169cfec8b423a381e71d jdk-9+164
a7942c3b1e59495dbf51dc7c41aab355fcd253d7 jdk-9+165

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -42,10 +42,10 @@ import jdk.internal.HotSpotIntrinsicCandidate;
* @author Andreas Sterbenz * @author Andreas Sterbenz
* @since 1.4.2 * @since 1.4.2
*/ */
final class CounterMode extends FeedbackCipher { class CounterMode extends FeedbackCipher {
// current counter value // current counter value
private final byte[] counter; final byte[] counter;
// encrypted bytes of the previous counter value // encrypted bytes of the previous counter value
private final byte[] encryptedCounter; private final byte[] encryptedCounter;

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -29,52 +29,43 @@
package com.sun.crypto.provider; package com.sun.crypto.provider;
import java.security.*; import javax.crypto.IllegalBlockSizeException;
import javax.crypto.*;
import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE; import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE;
/** /**
* This class represents the GCTR function defined in NIST 800-38D * This class represents the GCTR function defined in NIST 800-38D
* under section 6.5. It needs to be constructed w/ an initialized * under section 6.5. With a given cipher object and initial counter
* cipher object, and initial counter block(ICB). Given an input X * block, a counter mode operation is performed. Blocksize is limited
* of arbitrary length, it processes and returns an output which has * to 16 bytes.
* 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.
* *
* If any invariant is broken, failures can occur because the * If any invariant is broken, failures can occur because the
* AESCrypt.encryptBlock method can be intrinsified on the HotSpot VM * AESCrypt.encryptBlock method can be intrinsified on the HotSpot VM
* (see JDK-8067648 for details). * (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. * <p>This function is used in the implementation of GCM mode.
* *
* @since 1.8 * @since 1.8
*/ */
final class GCTR { final class GCTR extends CounterMode {
// these fields should not change after the object has been constructed
private final SymmetricCipher aes;
private final byte[] icb;
// 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) { GCTR(SymmetricCipher cipher, byte[] initialCounterBlk) {
this.aes = cipher; super(cipher);
if (initialCounterBlk.length != AES_BLOCK_SIZE) { if (initialCounterBlk.length != AES_BLOCK_SIZE) {
throw new RuntimeException("length of initial counter block (" + initialCounterBlk.length + throw new RuntimeException("length of initial counter block (" + initialCounterBlk.length +
") not equal to AES_BLOCK_SIZE (" + AES_BLOCK_SIZE + ")"); ") 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 // input must be multiples of 128-bit blocks when calling update
@ -89,23 +80,11 @@ final class GCTR {
throw new RuntimeException("output buffer too small"); throw new RuntimeException("output buffer too small");
} }
byte[] encryptedCntr = new byte[AES_BLOCK_SIZE]; return encrypt(in, inOfs, inLen, out, outOfs);
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;
} }
// input can be arbitrary size when calling doFinal // 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 { int outOfs) throws IllegalBlockSizeException {
try { try {
if (inLen < 0) { if (inLen < 0) {
@ -118,7 +97,7 @@ final class GCTR {
if (lastBlockSize != 0) { if (lastBlockSize != 0) {
// do the last partial block // do the last partial block
byte[] encryptedCntr = new byte[AES_BLOCK_SIZE]; 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++) { for (int n = 0; n < lastBlockSize; n++) {
out[outOfs + completeBlkLen + n] = out[outOfs + completeBlkLen + n] =
(byte) ((in[inOfs + completeBlkLen + n] ^ (byte) ((in[inOfs + completeBlkLen + n] ^
@ -131,28 +110,4 @@ final class GCTR {
} }
return inLen; 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;
}
}
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -209,6 +209,10 @@ public final class FilePermission extends Permission implements Serializable {
private static final Path here = builtInFS.getPath( private static final Path here = builtInFS.getPath(
GetPropertyAction.privilegedGetProperty("user.dir")); 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, * A private constructor that clones some and updates some,
* always with a different name. * always with a different name.
@ -341,7 +345,7 @@ public final class FilePermission extends Permission implements Serializable {
.normalize(); .normalize();
// lastName should always be non-null now // lastName should always be non-null now
Path lastName = npath.getFileName(); Path lastName = npath.getFileName();
if (lastName != null && lastName.toString().equals("-")) { if (lastName != null && lastName.equals(DASH_PATH)) {
directory = true; directory = true;
recursive = !rememberStar; recursive = !rememberStar;
npath = npath.getParent(); npath = npath.getParent();
@ -679,23 +683,76 @@ public final class FilePermission extends Permission implements Serializable {
* @return the depth in between * @return the depth in between
*/ */
private static int containsPath(Path p1, Path p2) { private static int containsPath(Path p1, Path p2) {
Path p;
try { // Two paths must have the same root. For example,
p = p2.relativize(p1).normalize(); // there is no contains relation between any two of
if (p.getName(0).toString().isEmpty()) { // "/x", "x", "C:/x", "C:x", and "//host/share/x".
return 0; if (!Objects.equals(p1.getRoot(), p2.getRoot())) {
} else {
for (Path item: p) {
String s = item.toString();
if (!s.equals("..")) {
return -1;
}
}
return p.getNameCount();
}
} catch (IllegalArgumentException iae) {
return -1; 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;
} }
/** /**

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -307,6 +307,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* sequence. * sequence.
*/ */
public int codePointAt(int index) { public int codePointAt(int index) {
int count = this.count;
byte[] value = this.value;
checkIndex(index, count); checkIndex(index, count);
if (isLatin1()) { if (isLatin1()) {
return value[index] & 0xff; return value[index] & 0xff;
@ -560,11 +562,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
val[count++] = 'l'; val[count++] = 'l';
val[count++] = 'l'; val[count++] = 'l';
} else { } else {
checkOffset(count + 4, val.length >> 1); count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
StringUTF16.putChar(val, count++, 'n');
StringUTF16.putChar(val, count++, 'u');
StringUTF16.putChar(val, count++, 'l');
StringUTF16.putChar(val, count++, 'l');
} }
this.count = count; this.count = count;
return this; return this;
@ -695,18 +693,9 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
} }
} else { } else {
if (b) { if (b) {
checkOffset(count + 4, val.length >> 1); count = StringUTF16.putCharsAt(val, count, 't', 'r', 'u', 'e');
StringUTF16.putChar(val, count++, 't');
StringUTF16.putChar(val, count++, 'r');
StringUTF16.putChar(val, count++, 'u');
StringUTF16.putChar(val, count++, 'e');
} else { } else {
checkOffset(count + 5, val.length >> 1); count = StringUTF16.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e');
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');
} }
} }
this.count = count; this.count = count;
@ -755,16 +744,15 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* @return a reference to this object. * @return a reference to this object.
*/ */
public AbstractStringBuilder append(int i) { public AbstractStringBuilder append(int i) {
int count = this.count;
int spaceNeeded = count + Integer.stringSize(i); int spaceNeeded = count + Integer.stringSize(i);
ensureCapacityInternal(spaceNeeded); ensureCapacityInternal(spaceNeeded);
if (isLatin1()) { if (isLatin1()) {
Integer.getChars(i, spaceNeeded, value); Integer.getChars(i, spaceNeeded, value);
} else { } else {
byte[] val = this.value; StringUTF16.getChars(i, count, spaceNeeded, value);
checkOffset(spaceNeeded, val.length >> 1);
Integer.getCharsUTF16(i, spaceNeeded, val);
} }
count = spaceNeeded; this.count = spaceNeeded;
return this; return this;
} }
@ -781,16 +769,15 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* @return a reference to this object. * @return a reference to this object.
*/ */
public AbstractStringBuilder append(long l) { public AbstractStringBuilder append(long l) {
int count = this.count;
int spaceNeeded = count + Long.stringSize(l); int spaceNeeded = count + Long.stringSize(l);
ensureCapacityInternal(spaceNeeded); ensureCapacityInternal(spaceNeeded);
if (isLatin1()) { if (isLatin1()) {
Long.getChars(l, spaceNeeded, value); Long.getChars(l, spaceNeeded, value);
} else { } else {
byte[] val = this.value; StringUTF16.getChars(l, count, spaceNeeded, value);
checkOffset(spaceNeeded, val.length >> 1);
Long.getCharsUTF16(l, spaceNeeded, val);
} }
count = spaceNeeded; this.count = spaceNeeded;
return this; return this;
} }
@ -843,6 +830,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* greater than {@code end}. * greater than {@code end}.
*/ */
public AbstractStringBuilder delete(int start, int end) { public AbstractStringBuilder delete(int start, int end) {
int count = this.count;
if (end > count) { if (end > count) {
end = count; end = count;
} }
@ -850,7 +838,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
int len = end - start; int len = end - start;
if (len > 0) { if (len > 0) {
shift(end, -len); shift(end, -len);
count -= len; this.count = count - len;
} }
return this; return this;
} }
@ -925,6 +913,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* greater than {@code end}. * greater than {@code end}.
*/ */
public AbstractStringBuilder replace(int start, int end, String str) { public AbstractStringBuilder replace(int start, int end, String str) {
int count = this.count;
if (end > count) { if (end > count) {
end = count; end = count;
} }
@ -933,7 +922,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
int newCount = count + len - (end - start); int newCount = count + len - (end - start);
ensureCapacityInternal(newCount); ensureCapacityInternal(newCount);
shift(end, newCount - count); shift(end, newCount - count);
count = newCount; this.count = newCount;
putStringAt(start, str); putStringAt(start, str);
return this; return this;
} }
@ -1500,40 +1489,11 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
val[k] = cj; val[k] = cj;
} }
} else { } else {
checkOffset(count, val.length >> 1); StringUTF16.reverse(val, count);
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);
}
} }
return this; 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. * Returns a string representing the data in this sequence.
* A new {@code String} object is allocated and initialized to * A new {@code String} object is allocated and initialized to
@ -1682,6 +1642,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
} }
private final void appendChars(char[] s, int off, int end) { private final void appendChars(char[] s, int off, int end) {
int count = this.count;
if (isLatin1()) { if (isLatin1()) {
byte[] val = this.value; byte[] val = this.value;
for (int i = off, j = count; i < end; i++) { for (int i = off, j = count; i < end; i++) {
@ -1689,17 +1650,17 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
if (StringLatin1.canEncode(c)) { if (StringLatin1.canEncode(c)) {
val[j++] = (byte)c; val[j++] = (byte)c;
} else { } else {
count = j; this.count = count = j;
inflate(); inflate();
StringUTF16.putCharsSB(this.value, j, s, i, end); StringUTF16.putCharsSB(this.value, j, s, i, end);
count += end - i; this.count = count + end - i;
return; return;
} }
} }
} else { } else {
StringUTF16.putCharsSB(this.value, count, s, off, end); 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) { private final void appendChars(CharSequence s, int off, int end) {

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -386,7 +386,7 @@ public final class Integer extends Number implements Comparable<Integer> {
} }
/** byte[]/UTF16 version */ /** 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 charPos = offset + len;
int radix = 1 << shift; int radix = 1 << shift;
int mask = radix - 1; int mask = radix - 1;
@ -442,7 +442,7 @@ public final class Integer extends Number implements Comparable<Integer> {
return new String(buf, LATIN1); return new String(buf, LATIN1);
} else { } else {
byte[] buf = new byte[size * 2]; byte[] buf = new byte[size * 2];
getCharsUTF16(i, size, buf); StringUTF16.getChars(i, size, buf);
return new String(buf, UTF16); return new String(buf, UTF16);
} }
} }
@ -516,49 +516,6 @@ public final class Integer extends Number implements Comparable<Integer> {
return charPos; 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. // Left here for compatibility reasons, see JDK-8143900.
static final int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999, static final int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE }; 99999999, 999999999, Integer.MAX_VALUE };

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -414,7 +414,7 @@ public final class Long extends Number implements Comparable<Long> {
} }
/** byte[]/UTF16 version */ /** 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 charPos = offset + len;
int radix = 1 << shift; int radix = 1 << shift;
int mask = radix - 1; int mask = radix - 1;
@ -475,7 +475,7 @@ public final class Long extends Number implements Comparable<Long> {
return new String(buf, LATIN1); return new String(buf, LATIN1);
} else { } else {
byte[] buf = new byte[size * 2]; byte[] buf = new byte[size * 2];
getCharsUTF16(i, size, buf); StringUTF16.getChars(i, size, buf);
return new String(buf, UTF16); return new String(buf, UTF16);
} }
} }
@ -561,61 +561,6 @@ public final class Long extends Number implements Comparable<Long> {
return charPos; return charPos;
} }
/**
* 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. * Returns the string representation size for a given long value.
* *

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -80,10 +80,10 @@ import java.util.stream.Stream;
* *
* <p>Subclasses of Process should override the {@link #onExit()} and * <p>Subclasses of Process should override the {@link #onExit()} and
* {@link #toHandle()} methods to provide a fully functional Process including the * {@link #toHandle()} methods to provide a fully functional Process including the
* {@link #getPid() process id}, * {@linkplain #pid() process id},
* {@link #info() information about the process}, * {@linkplain #info() information about the process},
* {@link #children() direct children}, and * {@linkplain #children() direct children}, and
* {@link #descendants() direct children plus descendants of those children} of the process. * {@linkplain #descendants() direct children plus descendants of those children} of the process.
* Delegating to the underlying Process or ProcessHandle is typically * Delegating to the underlying Process or ProcessHandle is typically
* easiest and most efficient. * easiest and most efficient.
* *
@ -237,14 +237,14 @@ public abstract class Process {
/** /**
* Kills the process. * Kills the process.
* Whether the process represented by this {@code Process} object is * 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. * implementation dependent.
* Forcible process destruction is defined as the immediate termination of a * Forcible process destruction is defined as the immediate termination of a
* process, whereas normal termination allows the process to shut down cleanly. * process, whereas normal termination allows the process to shut down cleanly.
* If the process is not alive, no action is taken. * If the process is not alive, no action is taken.
* <p> * <p>
* The {@link java.util.concurrent.CompletableFuture} from {@link #onExit} is * 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. * when the process has terminated.
*/ */
public abstract void destroy(); public abstract void destroy();
@ -257,7 +257,7 @@ public abstract class Process {
* If the process is not alive, no action is taken. * If the process is not alive, no action is taken.
* <p> * <p>
* The {@link java.util.concurrent.CompletableFuture} from {@link #onExit} is * 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. * when the process has terminated.
* <p> * <p>
* Invoking this method on {@code Process} objects returned by * Invoking this method on {@code Process} objects returned by
@ -335,15 +335,15 @@ public abstract class Process {
* *
* @implSpec * @implSpec
* The implementation of this method returns the process id as: * 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 * @return the native process id of the process
* @throws UnsupportedOperationException if the Process implementation * @throws UnsupportedOperationException if the Process implementation
* does not support this operation * does not support this operation
* @since 9 * @since 9
*/ */
public long getPid() { public long pid() {
return toHandle().getPid(); return toHandle().pid();
} }
/** /**
@ -357,9 +357,9 @@ public abstract class Process {
* <p> * <p>
* Calling {@code onExit().get()} waits for the process to terminate and returns * 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 * the Process. The future can be used to check if the process is
* {@link java.util.concurrent.CompletableFuture#isDone done} or to * {@linkplain java.util.concurrent.CompletableFuture#isDone done} or to
* {@link java.util.concurrent.CompletableFuture#get() wait} for it to terminate. * {@linkplain java.util.concurrent.CompletableFuture#get() wait} for it to terminate.
* {@link java.util.concurrent.CompletableFuture#cancel(boolean) Cancelling} * {@linkplain java.util.concurrent.CompletableFuture#cancel(boolean) Cancelling}
* the CompletableFuture does not affect the Process. * the CompletableFuture does not affect the Process.
* <p> * <p>
* Processes returned from {@link ProcessBuilder#start} override the * Processes returned from {@link ProcessBuilder#start} override the
@ -389,7 +389,7 @@ public abstract class Process {
* {@code waitFor} is interrupted, the thread's interrupt status is preserved. * {@code waitFor} is interrupted, the thread's interrupt status is preserved.
* <p> * <p>
* When {@link #waitFor()} returns successfully the CompletableFuture is * 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. * of the exit status of the process.
* *
* This implementation may consume a lot of memory for thread stacks if a * This implementation may consume a lot of memory for thread stacks if a
@ -463,7 +463,7 @@ public abstract class Process {
* This implementation throws an instance of * This implementation throws an instance of
* {@link java.lang.UnsupportedOperationException} and performs no other action. * {@link java.lang.UnsupportedOperationException} and performs no other action.
* Subclasses should override this method to provide a ProcessHandle for the * 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. * and {@link #descendants}, unless overridden, operate on the ProcessHandle.
* *
* @return Returns a ProcessHandle for the Process * @return Returns a ProcessHandle for the Process
@ -500,10 +500,10 @@ public abstract class Process {
/** /**
* Returns a snapshot of the direct children of the process. * Returns a snapshot of the direct children of the process.
* The parent of a direct child process is 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> * <p>
* <em>Note that processes are created and terminate asynchronously. * <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> * </em>
* *
* @implSpec * @implSpec
@ -526,10 +526,10 @@ public abstract class Process {
* Returns a snapshot of the descendants of the process. * Returns a snapshot of the descendants of the process.
* The descendants of a process are the children of the process * The descendants of a process are the children of the process
* plus the descendants of those children, recursively. * 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> * <p>
* <em>Note that processes are created and terminate asynchronously. * <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> * </em>
* *
* @implSpec * @implSpec

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -104,7 +104,7 @@ public interface ProcessHandle extends Comparable<ProcessHandle> {
* @throws UnsupportedOperationException if the implementation * @throws UnsupportedOperationException if the implementation
* does not support this operation * does not support this operation
*/ */
long getPid(); long pid();
/** /**
* Returns an {@code Optional<ProcessHandle>} for an existing native process. * Returns an {@code Optional<ProcessHandle>} for an existing native process.
@ -383,7 +383,7 @@ public interface ProcessHandle extends Comparable<ProcessHandle> {
/** /**
* Returns a hash code value for this ProcessHandle. * Returns a hash code value for this ProcessHandle.
* The hashcode value follows the general contract for {@link Object#hashCode()}. * 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. * may be a function of additional information to uniquely identify the process.
* If two ProcessHandles are equal according to the {@link #equals(Object) equals} * If two ProcessHandles are equal according to the {@link #equals(Object) equals}
* method, then calling the hashCode method on each of the two objects * method, then calling the hashCode method on each of the two objects

View File

@ -35,11 +35,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream; import java.util.stream.IntStream;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -176,7 +172,7 @@ final class ProcessHandleImpl implements ProcessHandle {
throw new IllegalStateException("onExit for current process not allowed"); throw new IllegalStateException("onExit for current process not allowed");
} }
return ProcessHandleImpl.completion(getPid(), false) return ProcessHandleImpl.completion(pid(), false)
.handleAsync((exitStatus, unusedThrowable) -> this); .handleAsync((exitStatus, unusedThrowable) -> this);
} }
@ -259,7 +255,7 @@ final class ProcessHandleImpl implements ProcessHandle {
* @return the native process ID * @return the native process ID
*/ */
@Override @Override
public long getPid() { public long pid() {
return pid; return pid;
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -1064,11 +1064,7 @@ public final class String
if (!isLatin1()) { // utf16 str and latin1 abs can never be "equal" if (!isLatin1()) { // utf16 str and latin1 abs can never be "equal"
return false; return false;
} }
for (int i = 0; i < len; i++) { return StringUTF16.contentEquals(v1, v2, len);
if ((char)(v1[i] & 0xff) != StringUTF16.getChar(v2, i)) {
return false;
}
}
} }
return true; return true;
} }
@ -1120,10 +1116,8 @@ public final class String
} }
} }
} else { } else {
for (int i = 0; i < n; i++) { if (!StringUTF16.contentEquals(val, cs, n)) {
if (StringUTF16.getChar(val, i) != cs.charAt(i)) { return false;
return false;
}
} }
} }
return true; return true;
@ -1734,6 +1728,9 @@ public final class String
if (tgtCount == 0) { if (tgtCount == 0) {
return fromIndex; return fromIndex;
} }
if (tgtCount > srcCount) {
return -1;
}
if (srcCoder == tgtCoder) { if (srcCoder == tgtCoder) {
return srcCoder == LATIN1 return srcCoder == LATIN1
? StringLatin1.indexOf(src, srcCount, tgt, tgtCount, fromIndex) ? StringLatin1.indexOf(src, srcCount, tgt, tgtCount, fromIndex)
@ -1792,7 +1789,7 @@ public final class String
* is the string being searched for. * is the string being searched for.
* *
* @param src the characters being searched. * @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 srcCount count of the source string.
* @param tgt the characters being searched for. * @param tgt the characters being searched for.
* @param fromIndex the index to begin searching from. * @param fromIndex the index to begin searching from.
@ -1807,12 +1804,12 @@ public final class String
* consistency, don't check for null str. * consistency, don't check for null str.
*/ */
int rightIndex = srcCount - tgtCount; int rightIndex = srcCount - tgtCount;
if (fromIndex < 0) {
return -1;
}
if (fromIndex > rightIndex) { if (fromIndex > rightIndex) {
fromIndex = rightIndex; fromIndex = rightIndex;
} }
if (fromIndex < 0) {
return -1;
}
/* Empty string always matches. */ /* Empty string always matches. */
if (tgtCount == 0) { if (tgtCount == 0) {
return fromIndex; return fromIndex;
@ -1825,31 +1822,8 @@ public final class String
if (srcCoder == LATIN1) { // && tgtCoder == UTF16 if (srcCoder == LATIN1) { // && tgtCoder == UTF16
return -1; return -1;
} }
// srcCoder == UTF16 && tgtCoder == LATIN1 // srcCoder == UTF16 && tgtCoder == LATIN1
int min = tgtCount - 1; return StringUTF16.lastIndexOfLatin1(src, srcCount, tgt, tgtCount, fromIndex);
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;
}
} }
/** /**
@ -3078,7 +3052,8 @@ public final class String
*/ */
static void checkIndex(int index, int length) { static void checkIndex(int index, int length) {
if (index < 0 || index >= length) { if (index < 0 || index >= length) {
throw new StringIndexOutOfBoundsException("index " + index); throw new StringIndexOutOfBoundsException("index " + index +
",length " + length);
} }
} }
@ -3116,7 +3091,7 @@ public final class String
* If {@code begin} is negative, {@code begin} is greater than * If {@code begin} is negative, {@code begin} is greater than
* {@code end}, or {@code end} is greater than {@code length}. * {@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) { if (begin < 0 || begin > end || end > length) {
throw new StringIndexOutOfBoundsException( throw new StringIndexOutOfBoundsException(
"begin " + begin + ", end " + end + ", length " + length); "begin " + begin + ", end " + end + ", length " + length);

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -293,7 +293,7 @@ final class StringConcatHelper {
if (coder == String.LATIN1) { if (coder == String.LATIN1) {
return Integer.getChars(value, index, buf); return Integer.getChars(value, index, buf);
} else { } else {
return Integer.getCharsUTF16(value, index, buf); return StringUTF16.getChars(value, index, buf);
} }
} }
@ -311,7 +311,7 @@ final class StringConcatHelper {
if (coder == String.LATIN1) { if (coder == String.LATIN1) {
return Long.getChars(value, index, buf); return Long.getChars(value, index, buf);
} else { } else {
return Long.getCharsUTF16(value, index, buf); return StringUTF16.getChars(value, index, buf);
} }
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -36,7 +36,6 @@ import jdk.internal.HotSpotIntrinsicCandidate;
import static java.lang.String.LATIN1; import static java.lang.String.LATIN1;
import static java.lang.String.UTF16; import static java.lang.String.UTF16;
import static java.lang.String.checkOffset; import static java.lang.String.checkOffset;
import static java.lang.String.checkBoundsOffCount;
final class StringLatin1 { final class StringLatin1 {
@ -566,11 +565,7 @@ final class StringLatin1 {
// inflatedCopy byte[] -> byte[] // inflatedCopy byte[] -> byte[]
@HotSpotIntrinsicCandidate @HotSpotIntrinsicCandidate
public static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) { 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 StringUTF16.inflate(src, srcOff, dst, dstOff, len);
checkBoundsOffCount(dstOff << 1, len << 1, dst.length);
for (int i = 0; i < len; i++) {
StringUTF16.putChar(dst, dstOff++, src[srcOff++] & 0xff);
}
} }
static class CharsSpliterator implements Spliterator.OfInt { static class CharsSpliterator implements Spliterator.OfInt {

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -30,12 +30,11 @@ import java.util.Locale;
import java.util.Spliterator; import java.util.Spliterator;
import java.util.function.IntConsumer; import java.util.function.IntConsumer;
import jdk.internal.HotSpotIntrinsicCandidate; 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.UTF16;
import static java.lang.String.LATIN1; 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 { final class StringUTF16 {
@ -51,33 +50,37 @@ final class StringUTF16 {
} }
@HotSpotIntrinsicCandidate @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; index <<= 1;
val[index++] = (byte)(c >> HI_BYTE_SHIFT); val[index++] = (byte)(c >> HI_BYTE_SHIFT);
val[index] = (byte)(c >> LO_BYTE_SHIFT); val[index] = (byte)(c >> LO_BYTE_SHIFT);
} }
@HotSpotIntrinsicCandidate @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; index <<= 1;
return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) | return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) |
((val[index] & 0xff) << LO_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) { public static int length(byte[] value) {
return value.length >> 1; 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); char c1 = getChar(value, index);
if (Character.isHighSurrogate(c1) && ++index < end) { if (Character.isHighSurrogate(c1) && ++index < end) {
if (checked) {
checkIndex(index, value);
}
char c2 = getChar(value, index); char c2 = getChar(value, index);
if (Character.isLowSurrogate(c2)) { if (Character.isLowSurrogate(c2)) {
return Character.toCodePoint(c1, c2); return Character.toCodePoint(c1, c2);
@ -86,10 +89,22 @@ final class StringUTF16 {
return c1; return c1;
} }
public static int codePointBefore(byte[] value, int index) { public static int codePointAt(byte[] value, int index, int end) {
char c2 = getChar(value, --index); 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) { 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)) { if (Character.isHighSurrogate(c1)) {
return Character.toCodePoint(c1, c2); return Character.toCodePoint(c1, c2);
} }
@ -97,11 +112,19 @@ final class StringUTF16 {
return c2; 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; 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++)) && if (Character.isHighSurrogate(getChar(value, i++)) &&
i < endIndex &&
Character.isLowSurrogate(getChar(value, i))) { Character.isLowSurrogate(getChar(value, i))) {
count--; count--;
i++; i++;
@ -110,6 +133,10 @@ final class StringUTF16 {
return count; 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) { public static char[] toChars(byte[] value) {
char[] dst = new char[value.length >> 1]; char[] dst = new char[value.length >> 1];
getChars(value, 0, dst.length, dst, 0); getChars(value, 0, dst.length, dst, 0);
@ -162,7 +189,7 @@ final class StringUTF16 {
@HotSpotIntrinsicCandidate @HotSpotIntrinsicCandidate
public static int compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len) { 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 // 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++) { for (int i = 0; i < len; i++) {
char c = getChar(src, srcOff); char c = getChar(src, srcOff);
if (c > 0xFF) { if (c > 0xFF) {
@ -212,7 +239,7 @@ final class StringUTF16 {
public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) { 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 // We need a range check here because 'getChar' has no checks
if (srcBegin < srcEnd) { if (srcBegin < srcEnd) {
checkBoundsOffCount(srcBegin << 1, (srcEnd - srcBegin) << 1, value.length); checkBoundsOffCount(srcBegin, srcEnd - srcBegin, value);
} }
for (int i = srcBegin; i < srcEnd; i++) { for (int i = srcBegin; i < srcEnd; i++) {
dst[dstBegin++] = getChar(value, i); dst[dstBegin++] = getChar(value, i);
@ -319,14 +346,25 @@ final class StringUTF16 {
if (str.length == 0) { if (str.length == 0) {
return 0; return 0;
} }
if (value.length == 0) { if (value.length < str.length) {
return -1; return -1;
} }
return indexOf(value, length(value), str, length(str), 0); return indexOfUnsafe(value, length(value), str, length(str), 0);
} }
@HotSpotIntrinsicCandidate @HotSpotIntrinsicCandidate
public static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) { 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); char first = getChar(str, 0);
int max = (valueCount - strCount); int max = (valueCount - strCount);
for (int i = fromIndex; i <= max; i++) { for (int i = fromIndex; i <= max; i++) {
@ -348,6 +386,7 @@ final class StringUTF16 {
return -1; return -1;
} }
/** /**
* Handles indexOf Latin1 substring in UTF16 string. * Handles indexOf Latin1 substring in UTF16 string.
*/ */
@ -356,14 +395,24 @@ final class StringUTF16 {
if (str.length == 0) { if (str.length == 0) {
return 0; return 0;
} }
if (value.length == 0) { if (length(value) < str.length) {
return -1; return -1;
} }
return indexOfLatin1(value, length(value), str, str.length, 0); return indexOfLatin1Unsafe(value, length(value), str, str.length, 0);
} }
@HotSpotIntrinsicCandidate @HotSpotIntrinsicCandidate
public static int indexOfLatin1(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) { 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); char first = (char)(tgt[0] & 0xff);
int max = (srcCount - tgtCount); int max = (srcCount - tgtCount);
for (int i = fromIndex; i <= max; i++) { for (int i = fromIndex; i <= max; i++) {
@ -389,6 +438,11 @@ final class StringUTF16 {
@HotSpotIntrinsicCandidate @HotSpotIntrinsicCandidate
private static int indexOfChar(byte[] value, int ch, int fromIndex, int max) { 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++) { for (int i = fromIndex; i < max; i++) {
if (getChar(value, i) == ch) { if (getChar(value, i) == ch) {
return i; return i;
@ -404,6 +458,7 @@ final class StringUTF16 {
if (Character.isValidCodePoint(ch)) { if (Character.isValidCodePoint(ch)) {
final char hi = Character.highSurrogate(ch); final char hi = Character.highSurrogate(ch);
final char lo = Character.lowSurrogate(ch); final char lo = Character.lowSurrogate(ch);
checkBoundsBeginEnd(fromIndex, max, value);
for (int i = fromIndex; i < max - 1; i++) { for (int i = fromIndex; i < max - 1; i++) {
if (getChar(value, i) == hi && getChar(value, i + 1 ) == lo) { if (getChar(value, i) == hi && getChar(value, i + 1 ) == lo) {
return i; return i;
@ -413,13 +468,21 @@ final class StringUTF16 {
return -1; return -1;
} }
// srcCoder == UTF16 && tgtCoder == UTF16
public static int lastIndexOf(byte[] src, int srcCount, public static int lastIndexOf(byte[] src, int srcCount,
byte[] tgt, int tgtCount, int fromIndex) { byte[] tgt, int tgtCount, int fromIndex) {
assert fromIndex >= 0;
assert tgtCount > 0;
assert tgtCount <= length(tgt);
int min = tgtCount - 1; int min = tgtCount - 1;
int i = min + fromIndex; int i = min + fromIndex;
int strLastIndex = tgtCount - 1; int strLastIndex = tgtCount - 1;
checkIndex(strLastIndex, tgt);
char strLastChar = getChar(tgt, strLastIndex); char strLastChar = getChar(tgt, strLastIndex);
checkIndex(i, src);
startSearchForLastChar: startSearchForLastChar:
while (true) { while (true) {
while (i >= min && getChar(src, i) != strLastChar) { while (i >= min && getChar(src, i) != strLastChar) {
@ -509,6 +572,9 @@ final class StringUTF16 {
public static boolean regionMatchesCI(byte[] value, int toffset, public static boolean regionMatchesCI(byte[] value, int toffset,
byte[] other, int ooffset, int len) { byte[] other, int ooffset, int len) {
int last = toffset + len; int last = toffset + len;
assert toffset >= 0 && ooffset >= 0;
assert ooffset + len <= length(other);
assert last <= length(value);
while (toffset < last) { while (toffset < last) {
char c1 = getChar(value, toffset++); char c1 = getChar(value, toffset++);
char c2 = getChar(other, ooffset++); char c2 = getChar(other, ooffset++);
@ -599,6 +665,8 @@ final class StringUTF16 {
private static String toLowerCaseEx(String str, byte[] value, private static String toLowerCaseEx(String str, byte[] value,
byte[] result, int first, Locale locale, byte[] result, int first, Locale locale,
boolean localeDependent) { boolean localeDependent) {
assert(result.length == value.length);
assert(first >= 0);
int resultOffset = first; int resultOffset = first;
int length = value.length >> 1; int length = value.length >> 1;
int srcCount; int srcCount;
@ -633,6 +701,8 @@ final class StringUTF16 {
System.arraycopy(result, 0, result2, 0, resultOffset << 1); System.arraycopy(result, 0, result2, 0, resultOffset << 1);
result = result2; result = result2;
} }
assert resultOffset >= 0;
assert resultOffset + mapLen <= length(result);
for (int x = 0; x < mapLen; ++x) { for (int x = 0; x < mapLen; ++x) {
putChar(result, resultOffset++, lowerCharArray[x]); putChar(result, resultOffset++, lowerCharArray[x]);
} }
@ -697,6 +767,8 @@ final class StringUTF16 {
byte[] result, int first, byte[] result, int first,
Locale locale, boolean localeDependent) Locale locale, boolean localeDependent)
{ {
assert(result.length == value.length);
assert(first >= 0);
int resultOffset = first; int resultOffset = first;
int length = value.length >> 1; int length = value.length >> 1;
int srcCount; int srcCount;
@ -733,10 +805,12 @@ final class StringUTF16 {
byte[] result2 = newBytesFor((result.length >> 1) + mapLen - srcCount); byte[] result2 = newBytesFor((result.length >> 1) + mapLen - srcCount);
System.arraycopy(result, 0, result2, 0, resultOffset << 1); System.arraycopy(result, 0, result2, 0, resultOffset << 1);
result = result2; 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]); putChar(result, resultOffset++, upperCharArray[x]);
} }
} }
} }
return newString(result, 0, resultOffset); return newString(result, 0, resultOffset);
@ -757,7 +831,7 @@ final class StringUTF16 {
null; 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) { while (off < end) {
putChar(val, index++, str[off++]); putChar(val, index++, str[off++]);
} }
@ -927,35 +1001,172 @@ final class StringUTF16 {
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
public static void putCharSB(byte[] val, int index, int c) { public static void putCharSB(byte[] val, int index, int c) {
checkIndex(index, val.length >> 1); checkIndex(index, val);
putChar(val, index, c); putChar(val, index, c);
} }
public static void putCharsSB(byte[] val, int index, char[] ca, int off, int end) { 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); putChars(val, index, ca, off, end);
} }
public static void putCharsSB(byte[] val, int index, CharSequence s, int off, int 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++) { for (int i = off; i < end; i++) {
putChar(val, index++, s.charAt(i)); putChar(val, index++, s.charAt(i));
} }
} }
public static int codePointAtSB(byte[] val, int index, int end) { public static int codePointAtSB(byte[] val, int index, int end) {
checkOffset(end, val.length >> 1); return codePointAt(val, index, end, true /* checked */);
return codePointAt(val, index, end);
} }
public static int codePointBeforeSB(byte[] val, int index) { public static int codePointBeforeSB(byte[] val, int index) {
checkOffset(index, val.length >> 1); return codePointBefore(val, index, true /* checked */);
return codePointBefore(val, index);
} }
public static int codePointCountSB(byte[] val, int beginIndex, int endIndex) { public static int codePointCountSB(byte[] val, int beginIndex, int endIndex) {
checkOffset(endIndex, val.length >> 1); return codePointCount(val, beginIndex, endIndex, true /* checked */);
return codePointCount(val, beginIndex, endIndex); }
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 @@ final class StringUTF16 {
} }
static final int MAX_LENGTH = Integer.MAX_VALUE >> 1; 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));
}
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -617,7 +617,7 @@ final class ProcessImpl extends Process {
} }
@Override @Override
public long getPid() { public long pid() {
return pid; return pid;
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -523,7 +523,7 @@ final class ProcessImpl extends Process {
@Override @Override
public CompletableFuture<Process> onExit() { public CompletableFuture<Process> onExit() {
return ProcessHandleImpl.completion(getPid(), false) return ProcessHandleImpl.completion(pid(), false)
.handleAsync((exitStatus, unusedThrowable) -> this); .handleAsync((exitStatus, unusedThrowable) -> this);
} }
@ -550,8 +550,8 @@ final class ProcessImpl extends Process {
private static native void terminateProcess(long handle); private static native void terminateProcess(long handle);
@Override @Override
public long getPid() { public long pid() {
return processHandle.getPid(); return processHandle.pid();
} }
private static native int getProcessId0(long handle); private static native int getProcessId0(long handle);
@ -572,7 +572,7 @@ final class ProcessImpl extends Process {
@Override @Override
public String toString() { public String toString() {
int exitCode = getExitCodeProcess(handle); 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(", exitValue=").append(exitCode == STILL_ACTIVE ? "\"not exited\"" : exitCode)
.append("]").toString(); .append("]").toString();
} }

View File

@ -1,4 +1,4 @@
## JPEG release 6b ## Independent JPEG Group: JPEG release 6b
### JPEG License ### JPEG License
<pre> <pre>

View File

@ -6,7 +6,8 @@
This notice is provided with respect to Elliptic Curve Cryptography, This notice is provided with respect to Elliptic Curve Cryptography,
which is included with JRE, JDK, and OpenJDK. 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 form with the JDK and OpenJDK source distributions, and as object code in
the JRE & JDK runtimes. the JRE & JDK runtimes.

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,6 +26,7 @@
package jdk.incubator.http; package jdk.incubator.http;
import java.io.IOException; import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.ProxySelector; import java.net.ProxySelector;
import java.net.SocketPermission; import java.net.SocketPermission;
@ -64,6 +65,9 @@ final class Exchange<T> {
final HttpRequestImpl request; final HttpRequestImpl request;
final HttpClientImpl client; final HttpClientImpl client;
volatile ExchangeImpl<T> exchImpl; 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 List<SocketPermission> permissions = new LinkedList<>();
final AccessControlContext acc; final AccessControlContext acc;
final MultiExchange<?,T> multi; final MultiExchange<?,T> multi;
@ -143,14 +147,80 @@ final class Exchange<T> {
} }
public void cancel() { 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) { if (exchImpl != null) {
exchImpl.cancel(); 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) { public void cancel(IOException cause) {
if (exchImpl != null) { // If the impl is non null, propagate the exception right away.
exchImpl.cancel(cause); // 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 @@ final class Exchange<T> {
} }
} }
// 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) private Response responseImpl0(HttpConnection connection)
throws IOException, InterruptedException throws IOException, InterruptedException
{ {
exchImpl = ExchangeImpl.get(this, connection); establishExchange(connection);
exchImpl.setClientForRequest(requestProcessor); exchImpl.setClientForRequest(requestProcessor);
if (request.expectContinue()) { if (request.expectContinue()) {
Log.logTrace("Sending Expect: 100-Continue"); Log.logTrace("Sending Expect: 100-Continue");
@ -257,7 +343,7 @@ final class Exchange<T> {
CompletableFuture<Response> responseAsyncImpl0(HttpConnection connection) { CompletableFuture<Response> responseAsyncImpl0(HttpConnection connection) {
try { try {
exchImpl = ExchangeImpl.get(this, connection); establishExchange(connection);
} catch (IOException | InterruptedException e) { } catch (IOException | InterruptedException e) {
return MinimalFuture.failedFuture(e); return MinimalFuture.failedFuture(e);
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -46,9 +46,12 @@ import jdk.incubator.http.internal.common.Utils;
class Http1Exchange<T> extends ExchangeImpl<T> { class Http1Exchange<T> extends ExchangeImpl<T> {
final HttpRequestImpl request; // main request final HttpRequestImpl request; // main request
final List<CompletableFuture<?>> operations; // used for cancel private final List<CompletableFuture<?>> operations; // used for cancel
final Http1Request requestAction; 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 HttpConnection connection;
final HttpClientImpl client; final HttpClientImpl client;
final Executor executor; final Executor executor;
@ -70,7 +73,7 @@ class Http1Exchange<T> extends ExchangeImpl<T> {
this.request = exchange.request(); this.request = exchange.request();
this.client = exchange.client(); this.client = exchange.client();
this.executor = exchange.executor(); this.executor = exchange.executor();
this.operations = Collections.synchronizedList(new LinkedList<>()); this.operations = new LinkedList<>();
this.buffer = exchange.getBuffer(); this.buffer = exchange.getBuffer();
if (connection != null) { if (connection != null) {
this.connection = connection; this.connection = connection;
@ -186,9 +189,22 @@ class Http1Exchange<T> extends ExchangeImpl<T> {
} }
connection.close(); connection.close();
int count = 0; int count = 0;
for (CompletableFuture<?> cf : operations) { if (operations.isEmpty()) {
cf.completeExceptionally(cause); failed = cause;
count++; 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); Log.logError("Http1Exchange.cancel: count=" + count);
} }
@ -206,8 +222,24 @@ class Http1Exchange<T> extends ExchangeImpl<T> {
CompletableFuture<Response> cf = CompletableFuture<Response> cf =
connection.whenReceivingResponse() connection.whenReceivingResponse()
.thenCompose((v) -> getResponseAsyncImpl(executor)); .thenCompose((v) -> getResponseAsyncImpl(executor));
IOException cause;
operations.add(cf); 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; return cf;
} }
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -582,12 +582,14 @@ class HttpClientImpl extends HttpClient {
// Timers are implemented through timed Selector.select() calls. // Timers are implemented through timed Selector.select() calls.
synchronized void registerTimer(TimeoutEvent event) { synchronized void registerTimer(TimeoutEvent event) {
Log.logTrace("Registering timer {0}", event);
timeouts.add(event); timeouts.add(event);
selmgr.wakeupSelector(); selmgr.wakeupSelector();
} }
synchronized void cancelTimer(TimeoutEvent event) { 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 @@ class HttpClientImpl extends HttpClient {
* returns the amount of time, in milliseconds, until the next earliest * returns the amount of time, in milliseconds, until the next earliest
* event. A return value of 0 means that there are no events. * event. A return value of 0 means that there are no events.
*/ */
private synchronized long purgeTimeoutsAndReturnNextDeadline() { private long purgeTimeoutsAndReturnNextDeadline() {
if (timeouts.isEmpty()) long diff = 0L;
return 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(); Instant now = Instant.now();
Iterator<TimeoutEvent> itr = timeouts.iterator(); Iterator<TimeoutEvent> itr = timeouts.iterator();
while (itr.hasNext()) { while (itr.hasNext()) {
TimeoutEvent event = itr.next(); TimeoutEvent event = itr.next();
long diff = now.until(event.deadline(), ChronoUnit.MILLIS); diff = now.until(event.deadline(), ChronoUnit.MILLIS);
if (diff <= 0) { if (diff <= 0) {
itr.remove(); itr.remove();
event.handle(); // TODO: release lock. toHandle = (toHandle == null) ? new ArrayList<>() : toHandle;
} else { toHandle.add(event);
return diff; } else {
break;
}
} }
remaining = timeouts.size();
} }
return 0L;
// 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 time to wait until next event. 0L if there's no more events.
return diff < 0 ? 0L : diff;
} }
// used for the connection window // used for the connection window

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -357,9 +357,5 @@ class MultiExchange<U,T> {
public void handle() { public void handle() {
cancel(new HttpTimeoutException("request timed out")); cancel(new HttpTimeoutException("request timed out"));
} }
@Override
public String toString() {
return "[deadline = " + deadline() + "]";
}
} }
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -54,7 +54,7 @@ import jdk.incubator.http.internal.common.Utils;
*/ */
class PlainHttpConnection extends HttpConnection implements AsyncConnection { class PlainHttpConnection extends HttpConnection implements AsyncConnection {
protected SocketChannel chan; protected final SocketChannel chan;
private volatile boolean connected; private volatile boolean connected;
private boolean closed; private boolean closed;
@ -100,6 +100,7 @@ class PlainHttpConnection extends HttpConnection implements AsyncConnection {
chan.finishConnect(); chan.finishConnect();
} catch (IOException e) { } catch (IOException e) {
cf.completeExceptionally(e); cf.completeExceptionally(e);
return;
} }
connected = true; connected = true;
cf.complete(null); cf.complete(null);

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -670,11 +670,21 @@ class Stream<T> extends ExchangeImpl<T> {
@Override @Override
CompletableFuture<Response> getResponseAsync(Executor executor) { 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) { synchronized (response_cfs) {
if (!response_cfs.isEmpty()) { if (!response_cfs.isEmpty()) {
// This CompletableFuture was created by completeResponse().
// it will be already completed.
cf = response_cfs.remove(0); 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 { } else {
// getResponseAsync() is called first. Create a CompletableFuture
// that will be completed by completeResponse() when
// completeResponse() is called.
cf = new MinimalFuture<>(); cf = new MinimalFuture<>();
response_cfs.add(cf); response_cfs.add(cf);
} }
@ -708,7 +718,7 @@ class Stream<T> extends ExchangeImpl<T> {
cf.complete(resp); cf.complete(resp);
response_cfs.remove(cf); response_cfs.remove(cf);
return; return;
} } // else we found the previous response: just leave it alone.
} }
cf = MinimalFuture.completedFuture(resp); cf = MinimalFuture.completedFuture(resp);
Log.logTrace("Created completed future (streamid={0}): {1}", Log.logTrace("Created completed future (streamid={0}): {1}",
@ -742,10 +752,13 @@ class Stream<T> extends ExchangeImpl<T> {
*/ */
void completeResponseExceptionally(Throwable t) { void completeResponseExceptionally(Throwable t) {
synchronized (response_cfs) { 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()) { if (!cf.isDone()) {
cf.completeExceptionally(t); cf.completeExceptionally(t);
response_cfs.remove(cf); response_cfs.remove(i);
return; return;
} }
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,10 +27,11 @@ package jdk.incubator.http;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.concurrent.atomic.AtomicLong;
/** /**
* Timeout event notified by selector thread. Executes the given handler if * 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)}. * Register with {@link HttpClientImpl#registerTimer(TimeoutEvent)}.
* *
@ -38,6 +39,10 @@ import java.time.Instant;
*/ */
abstract class TimeoutEvent implements Comparable<TimeoutEvent> { 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; private final Instant deadline;
TimeoutEvent(Duration duration) { TimeoutEvent(Duration duration) {
@ -52,6 +57,24 @@ abstract class TimeoutEvent implements Comparable<TimeoutEvent> {
@Override @Override
public int compareTo(TimeoutEvent other) { 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 + "]";
} }
} }

View File

@ -47,8 +47,6 @@ import javax.management.openmbean.CompositeData;
* object was constructed. The value of the VM option * object was constructed. The value of the VM option
* may be changed after the {@code VMOption} object was constructed, * 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 * @author Mandy Chung
* @since 1.6 * @since 1.6
*/ */

View File

@ -170,8 +170,6 @@ java/net/MulticastSocket/Test.java 7145658 macosx-a
java/net/DatagramSocket/SendDatagramToBadAddress.java 7143960 macosx-all java/net/DatagramSocket/SendDatagramToBadAddress.java 7143960 macosx-all
java/net/httpclient/TimeoutOrdering.java 8170940 solaris-all,windows-all
############################################################################ ############################################################################
# jdk_nio # jdk_nio

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,13 +23,11 @@
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List;
import java.util.Map; import java.util.Map;
import jdk.testlibrary.ProcessTools; import jdk.testlibrary.ProcessTools;
import com.sun.jdi.Bootstrap; import com.sun.jdi.Bootstrap;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.VirtualMachine; import com.sun.jdi.VirtualMachine;
import com.sun.jdi.connect.AttachingConnector; import com.sun.jdi.connect.AttachingConnector;
import com.sun.jdi.connect.Connector; import com.sun.jdi.connect.Connector;
@ -86,7 +84,7 @@ public class ProcessAttachTest {
is.read(); is.read();
// Attach a debugger // Attach a debugger
tryDebug(p.getPid()); tryDebug(p.pid());
} finally { } finally {
p.destroyForcibly(); p.destroyForcibly();
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -89,12 +89,14 @@ public class Correctness {
//check("/-", "-"); //check("/-", "-");
try { try {
// containsPath is broken on Windows.
containsMethod = FilePermission.class.getDeclaredMethod( containsMethod = FilePermission.class.getDeclaredMethod(
"containsPath", Path.class, Path.class); "containsPath", Path.class, Path.class);
containsMethod.setAccessible(true); containsMethod.setAccessible(true);
System.out.println(); 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", 0);
contains("x", "x/y", 1); contains("x", "x/y", 1);
contains("x", "x/y/z", 2); contains("x", "x/y/z", 2);
@ -160,7 +162,7 @@ public class Correctness {
} }
} }
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 fp1 = new FilePermission(s1, "read");
FilePermission fp2 = new FilePermission(s2, "read"); FilePermission fp2 = new FilePermission(s2, "read");
boolean b = fp1.implies(fp2); boolean b = fp1.implies(fp2);
@ -173,6 +175,16 @@ public class Correctness {
} }
} }
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) { static void check(String s1, String s2) {
check(s1, s2, true); check(s1, s2, true);
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -311,7 +311,7 @@ public class Basic {
if (action.equals("sleep")) { if (action.equals("sleep")) {
Thread.sleep(10 * 60 * 1000L); Thread.sleep(10 * 60 * 1000L);
} else if (action.equals("pid")) { } else if (action.equals("pid")) {
System.out.println(ProcessHandle.current().getPid()); System.out.println(ProcessHandle.current().pid());
} else if (action.equals("testIO")) { } else if (action.equals("testIO")) {
String expected = "standard input"; String expected = "standard input";
char[] buf = new char[expected.length()+1]; char[] buf = new char[expected.length()+1];
@ -1235,7 +1235,7 @@ public class Basic {
Process p = pb.start(); Process p = pb.start();
String s = commandOutput(p); String s = commandOutput(p);
long actualPid = Long.valueOf(s.trim()); long actualPid = Long.valueOf(s.trim());
long expectedPid = p.getPid(); long expectedPid = p.pid();
equal(actualPid, expectedPid); equal(actualPid, expectedPid);
} catch (Throwable t) { } catch (Throwable t) {
unexpected(t); unexpected(t);
@ -1245,7 +1245,7 @@ public class Basic {
// Test the default implementation of Process.getPid // Test the default implementation of Process.getPid
DelegatingProcess p = new DelegatingProcess(null); DelegatingProcess p = new DelegatingProcess(null);
THROWS(UnsupportedOperationException.class, THROWS(UnsupportedOperationException.class,
() -> p.getPid(), () -> p.pid(),
() -> p.toHandle(), () -> p.toHandle(),
() -> p.supportsNormalTermination(), () -> p.supportsNormalTermination(),
() -> p.children(), () -> p.children(),
@ -2243,7 +2243,7 @@ public class Basic {
// Child process waits until it gets input // Child process waits until it gets input
String s = p.toString(); String s = p.toString();
check(s.contains("not exited")); check(s.contains("not exited"));
check(s.contains("pid=" + p.getPid() + ",")); check(s.contains("pid=" + p.pid() + ","));
new PrintStream(p.getOutputStream()).print("standard input"); new PrintStream(p.getOutputStream()).print("standard input");
p.getOutputStream().close(); p.getOutputStream().close();
@ -2251,7 +2251,7 @@ public class Basic {
// Check the toString after it exits // Check the toString after it exits
int exitValue = p.waitFor(); int exitValue = p.waitFor();
s = p.toString(); s = p.toString();
check(s.contains("pid=" + p.getPid() + ",")); check(s.contains("pid=" + p.pid() + ","));
check(s.contains("exitValue=" + exitValue) && check(s.contains("exitValue=" + exitValue) &&
!s.contains("not exited")); !s.contains("not exited"));
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -212,7 +212,7 @@ public class PipelineTest {
static void print(ProcessHandle p) { static void print(ProcessHandle p) {
System.out.printf("process: pid: %d, info: %s%n", System.out.printf("process: pid: %d, info: %s%n",
p.getPid(), p.info()); p.pid(), p.info());
} }
// Check various aspects of the processes // Check various aspects of the processes

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -43,7 +43,7 @@ public class Zombies {
! new File("/bin/ps").canExecute()) ! new File("/bin/ps").canExecute())
return; return;
System.out.println("Looks like a Unix system."); 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); System.out.printf("mypid: %d%n", mypid);
final Runtime rt = Runtime.getRuntime(); final Runtime rt = Runtime.getRuntime();
@ -65,7 +65,7 @@ public class Zombies {
Process p = rt.exec(TrueCommand); Process p = rt.exec(TrueCommand);
ProcessHandle pp = p.toHandle().parent().orElse(null); 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(); p.waitFor();
// Count all the zombies that are children of this Java process // Count all the zombies that are children of this Java process

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -66,13 +66,13 @@ public class Basic {
public static void test2() { public static void test2() {
try { try {
ProcessHandle self = ProcessHandle.current(); 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); Optional<ProcessHandle> self1 = ProcessHandle.of(pid);
assertEquals(self1.get(), self, 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); Optional<ProcessHandle> ph = ProcessHandle.of(pid);
assertEquals(pid, ph.get().getPid()); assertEquals(pid, ph.get().pid());
} finally { } finally {
// Cleanup any left over processes // Cleanup any left over processes
ProcessHandle.current().children().forEach(ProcessHandle::destroy); ProcessHandle.current().children().forEach(ProcessHandle::destroy);
@ -98,7 +98,7 @@ public class Basic {
Process p = new ProcessBuilder("sleep", "0").start(); Process p = new ProcessBuilder("sleep", "0").start();
p.waitFor(); p.waitFor();
long deadPid = p.getPid(); long deadPid = p.pid();
p = null; // Forget the process p = null; // Forget the process
Optional<ProcessHandle> t = ProcessHandle.of(deadPid); Optional<ProcessHandle> t = ProcessHandle.of(deadPid);

View File

@ -159,7 +159,7 @@ private static volatile int commandSeq = 0; // Command sequence number
*/ */
CompletableFuture<String> forEachOutputLine(Consumer<String> consumer) { CompletableFuture<String> forEachOutputLine(Consumer<String> consumer) {
final CompletableFuture<String> future = new CompletableFuture<>(); final CompletableFuture<String> future = new CompletableFuture<>();
String name = "OutputLineReader-" + getPid(); String name = "OutputLineReader-" + pid();
Thread t = new Thread(() -> { Thread t = new Thread(() -> {
try (BufferedReader reader = outputReader()) { try (BufferedReader reader = outputReader()) {
String line; String line;
@ -167,7 +167,7 @@ private static volatile int commandSeq = 0; // Command sequence number
consumer.accept(line); consumer.accept(line);
} }
} catch (IOException | RuntimeException ex) { } catch (IOException | RuntimeException ex) {
consumer.accept("IOE (" + getPid() + "):" + ex.getMessage()); consumer.accept("IOE (" + pid() + "):" + ex.getMessage());
future.completeExceptionally(ex); future.completeExceptionally(ex);
} }
future.complete("success"); future.complete("success");
@ -327,7 +327,7 @@ private static volatile int commandSeq = 0; // Command sequence number
try { try {
p.getOutputStream().close(); p.getOutputStream().close();
} catch (IOException ie) { } catch (IOException ie) {
sendResult("stdin_closing", p.getPid(), sendResult("stdin_closing", p.pid(),
"exception", ie.getMessage()); "exception", ie.getMessage());
} }
} }
@ -352,9 +352,9 @@ private static volatile int commandSeq = 0; // Command sequence number
"children to terminate%n"); "children to terminate%n");
children.removeAll(completedChildren); children.removeAll(completedChildren);
for (JavaChild c : children) { for (JavaChild c : children) {
sendResult("stdin_noterm", c.getPid()); sendResult("stdin_noterm", c.pid());
System.err.printf(" Process not terminated: " + System.err.printf(" Process not terminated: " +
"pid: %d%n", c.getPid()); "pid: %d%n", c.pid());
} }
System.exit(2); System.exit(2);
} }
@ -386,11 +386,11 @@ private static volatile int commandSeq = 0; // Command sequence number
System.arraycopy(args, nextArg, subargs, 0, subargs.length); System.arraycopy(args, nextArg, subargs, 0, subargs.length);
for (int i = 0; i < ncount; i++) { for (int i = 0; i < ncount; i++) {
JavaChild p = spawnJavaChild(subargs); JavaChild p = spawnJavaChild(subargs);
sendResult(action, p.getPid()); sendResult(action, p.pid());
p.forEachOutputLine(JavaChild::sendRaw); p.forEachOutputLine(JavaChild::sendRaw);
p.onJavaChildExit().thenAccept((p1) -> { p.onJavaChildExit().thenAccept((p1) -> {
int excode = p1.exitValue(); int excode = p1.exitValue();
sendResult("child_exit", p1.getPid(), excode); sendResult("child_exit", p1.pid(), excode);
completedChildren.add(p1); completedChildren.add(p1);
}); });
children.add(p); // Add child to spawned list children.add(p); // Add child to spawned list
@ -410,7 +410,7 @@ private static volatile int commandSeq = 0; // Command sequence number
if (p.isAlive()) { if (p.isAlive()) {
sentCount++; sentCount++;
// overwrite with current pid // overwrite with current pid
result[0] = Long.toString(p.getPid()); result[0] = Long.toString(p.pid());
sendResult(action, result); sendResult(action, result);
p.sendAction(args[nextArg], subargs); p.sendAction(args[nextArg], subargs);
} }
@ -426,7 +426,7 @@ private static volatile int commandSeq = 0; // Command sequence number
// ignoring those that are not alive // ignoring those that are not alive
for (JavaChild p : children) { for (JavaChild p : children) {
if (p.isAlive()) { if (p.isAlive()) {
sendResult(action, p.getPid()); sendResult(action, p.pid());
p.getOutputStream().close(); p.getOutputStream().close();
} }
} }
@ -505,7 +505,7 @@ private static volatile int commandSeq = 0; // Command sequence number
String command; String command;
Object[] results; Object[] results;
Event(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) { Event(long pid, int seq, String command, Object... results) {
this.pid = pid; this.pid = pid;

View File

@ -104,7 +104,7 @@ public class OnExitTest extends ProcessUtil {
JavaChild proc = JavaChild.spawnJavaChild("stdin"); JavaChild proc = JavaChild.spawnJavaChild("stdin");
procHandle = proc.toHandle(); procHandle = proc.toHandle();
printf(" spawned: %d%n", proc.getPid()); printf(" spawned: %d%n", proc.pid());
proc.forEachOutputLine((s) -> { proc.forEachOutputLine((s) -> {
String[] split = s.trim().split(" "); String[] split = s.trim().split(" ");
@ -235,7 +235,7 @@ public class OnExitTest extends ProcessUtil {
} while (!"pid".equals(split[1])); } while (!"pid".equals(split[1]));
// Tell B to wait for A's pid // 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 // Wait a bit to see if B will prematurely report the termination of A
try { try {

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -199,7 +199,7 @@ public abstract class ProcessUtil {
*/ */
static void printProcess(ProcessHandle ph, String prefix) { static void printProcess(ProcessHandle ph, String prefix) {
printf("%spid %s, alive: %s; parent: %s, %s%n", 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());
} }
/** /**

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -73,7 +73,7 @@ public class TreeTest extends ProcessUtil {
try { try {
ProcessHandle self = ProcessHandle.current(); ProcessHandle self = ProcessHandle.current();
printf("self pid: %d%n", self.getPid()); printf("self pid: %d%n", self.pid());
printDeep(self, ""); printDeep(self, "");
for (int i = 0; i < MAXCHILDREN; i++) { for (int i = 0; i < MAXCHILDREN; i++) {
@ -154,7 +154,7 @@ public class TreeTest extends ProcessUtil {
JavaChild p1 = JavaChild.spawnJavaChild("stdin"); JavaChild p1 = JavaChild.spawnJavaChild("stdin");
ProcessHandle p1Handle = p1.toHandle(); 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 // Gather the PIDs from the output of the spawing process
p1.forEachOutputLine((s) -> { p1.forEachOutputLine((s) -> {
@ -206,7 +206,7 @@ public class TreeTest extends ProcessUtil {
// show the complete list of children (for debug) // show the complete list of children (for debug)
List<ProcessHandle> descendants = getDescendants(p1Handle); List<ProcessHandle> descendants = getDescendants(p1Handle);
printf(" descendants: %s%n", printf(" descendants: %s%n",
descendants.stream().map(p -> p.getPid()) descendants.stream().map(p -> p.pid())
.collect(Collectors.toList())); .collect(Collectors.toList()));
// Verify that all spawned children show up in the descendants List // Verify that all spawned children show up in the descendants List
@ -252,7 +252,7 @@ public class TreeTest extends ProcessUtil {
JavaChild p1 = JavaChild.spawnJavaChild("stdin"); JavaChild p1 = JavaChild.spawnJavaChild("stdin");
ProcessHandle p1Handle = p1.toHandle(); ProcessHandle p1Handle = p1.toHandle();
printf(" p1: %s%n", p1.getPid()); printf(" p1: %s%n", p1.pid());
int newChildren = 3; int newChildren = 3;
CountDownLatch spawnCount = new CountDownLatch(newChildren); CountDownLatch spawnCount = new CountDownLatch(newChildren);
@ -356,11 +356,11 @@ public class TreeTest extends ProcessUtil {
parent[sortindex[i]] = processes[sortindex[i]].parent().orElse(null); parent[sortindex[i]] = processes[sortindex[i]].parent().orElse(null);
} }
Arrays.sort(sortindex, (i1, i2) -> { Arrays.sort(sortindex, (i1, i2) -> {
int cmp = Long.compare((parent[i1] == null ? 0L : parent[i1].getPid()), int cmp = Long.compare((parent[i1] == null ? 0L : parent[i1].pid()),
(parent[i2] == null ? 0L : parent[i2].getPid())); (parent[i2] == null ? 0L : parent[i2].pid()));
if (cmp == 0) { if (cmp == 0) {
cmp = Long.compare((processes[i1] == null ? 0L : processes[i1].getPid()), cmp = Long.compare((processes[i1] == null ? 0L : processes[i1].pid()),
(processes[i2] == null ? 0L : processes[i2].getPid())); (processes[i2] == null ? 0L : processes[i2].pid()));
} }
return cmp; return cmp;
}); });
@ -397,7 +397,7 @@ public class TreeTest extends ProcessUtil {
ProcessHandle p1Handle = p1.toHandle(); ProcessHandle p1Handle = p1.toHandle();
printf("Spawning %d x %d x %d processes, pid: %d%n", 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 // Start the first tier of subprocesses
p1.sendAction("spawn", factor, "stdin"); p1.sendAction("spawn", factor, "stdin");
@ -448,7 +448,7 @@ public class TreeTest extends ProcessUtil {
List<ProcessHandle> subprocesses = getDescendants(p1Handle); List<ProcessHandle> subprocesses = getDescendants(p1Handle);
printf(" descendants: %s%n", printf(" descendants: %s%n",
subprocesses.stream().map(p -> p.getPid()) subprocesses.stream().map(p -> p.pid())
.collect(Collectors.toList())); .collect(Collectors.toList()));
p1.getOutputStream().close(); // Close stdin for the controlling p1 p1.getOutputStream().close(); // Close stdin for the controlling p1

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -80,10 +80,10 @@ public class SleepyCat {
for (Process p : pids) { for (Process p : pids) {
if (p == null) if (p == null)
continue; continue;
String[] pfiles = {"pfiles", Long.toString(p.getPid())}; String[] pfiles = {"pfiles", Long.toString(p.pid())};
fds = new ProcessBuilder(pfiles).inheritIO().start(); fds = new ProcessBuilder(pfiles).inheritIO().start();
fds.waitFor(); fds.waitFor();
String[] pstack = {"pstack", Long.toString(p.getPid())}; String[] pstack = {"pstack", Long.toString(p.pid())};
fds = new ProcessBuilder(pstack).inheritIO().start(); fds = new ProcessBuilder(pstack).inheritIO().start();
fds.waitFor(); fds.waitFor();
} }

View File

@ -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);
}
}

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -43,6 +43,9 @@ import static jdk.incubator.http.HttpResponse.BodyHandler.discard;
* @run main/othervm TimeoutOrdering * @run main/othervm TimeoutOrdering
*/ */
// To enable logging use
// @run main/othervm -Djdk.httpclient.HttpClient.log=all,frames:all TimeoutOrdering
public class TimeoutOrdering { public class TimeoutOrdering {
// The assumption is that 5 secs is sufficiently large enough, without being // The assumption is that 5 secs is sufficiently large enough, without being
@ -81,6 +84,8 @@ public class TimeoutOrdering {
if (t != null) { if (t != null) {
if (!(t.getCause() instanceof HttpTimeoutException)) { if (!(t.getCause() instanceof HttpTimeoutException)) {
out.println("Wrong exception type:" + t.toString()); out.println("Wrong exception type:" + t.toString());
Throwable c = t.getCause() == null ? t : t.getCause();
c.printStackTrace();
error = true; error = true;
} else { } else {
out.println("Caught expected timeout: " + t.getCause()); out.println("Caught expected timeout: " + t.getCause());
@ -116,6 +121,8 @@ public class TimeoutOrdering {
out.println("Caught expected timeout: " + e); out.println("Caught expected timeout: " + e);
queue.offer(req); queue.offer(req);
} catch (IOException | InterruptedException ee) { } catch (IOException | InterruptedException ee) {
Throwable c = ee.getCause() == null ? ee : ee.getCause();
c.printStackTrace();
error = true; error = true;
} }
}); });

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -263,7 +263,7 @@ public class LoggingDeadlock2 {
sleep(ms); sleep(ms);
System.err.println("Timeout reached: " + ms); System.err.println("Timeout reached: " + ms);
if (process.isAlive()) { if (process.isAlive()) {
long pid = process.getPid(); long pid = process.pid();
ProcessBuilder jstack = new ProcessBuilder(jstackExe, String.valueOf(pid)); ProcessBuilder jstack = new ProcessBuilder(jstackExe, String.valueOf(pid));
System.err.println("Dumping subprocess stack: " + pid); System.err.println("Dumping subprocess stack: " + pid);
Process p = jstack.inheritIO().start(); Process p = jstack.inheritIO().start();

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,7 +26,6 @@ package jdk.testlibrary;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate; import java.util.function.Predicate;
/** /**
@ -195,7 +194,7 @@ public class ProcessThread extends TestThread {
* @return The PID associated with this process runnable * @return The PID associated with this process runnable
*/ */
public long getPid() throws InterruptedException { public long getPid() throws InterruptedException {
return getProcess().getPid(); return getProcess().pid();
} }
public void sendMessage(String message) throws InterruptedException { public void sendMessage(String message) throws InterruptedException {

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -256,7 +256,7 @@ public final class ProcessTools {
* @return Process id * @return Process id
*/ */
public static long getProcessId() { public static long getProcessId() {
return ProcessHandle.current().getPid(); return ProcessHandle.current().pid();
} }
/** /**
@ -542,8 +542,8 @@ public final class ProcessTools {
} }
@Override @Override
public long getPid() { public long pid() {
return p.getPid(); return p.pid();
} }
@Override @Override

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -144,7 +144,7 @@ public class CustomLauncherTest {
System.out.println("Attaching test manager:"); System.out.println("Attaching test manager:");
System.out.println("========================="); System.out.println("=========================");
System.out.println(" PID : " + serverPrc.getPid()); System.out.println(" PID : " + serverPrc.pid());
System.out.println(" shutdown port : " + port.get()); System.out.println(" shutdown port : " + port.get());
ProcessBuilder client = ProcessTools.createJavaProcessBuilder( ProcessBuilder client = ProcessTools.createJavaProcessBuilder(
@ -152,7 +152,7 @@ public class CustomLauncherTest {
TEST_CLASSPATH, TEST_CLASSPATH,
"--add-exports", "jdk.management.agent/jdk.internal.agent=ALL-UNNAMED", "--add-exports", "jdk.management.agent/jdk.internal.agent=ALL-UNNAMED",
"TestManager", "TestManager",
String.valueOf(serverPrc.getPid()), String.valueOf(serverPrc.pid()),
port.get(), port.get(),
"true" "true"
); );

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -129,7 +129,7 @@ public class LocalManagementTest {
System.out.println("Attaching test manager:"); System.out.println("Attaching test manager:");
System.out.println("========================="); System.out.println("=========================");
System.out.println(" PID : " + serverPrc.getPid()); System.out.println(" PID : " + serverPrc.pid());
System.out.println(" shutdown port : " + port.get()); System.out.println(" shutdown port : " + port.get());
ProcessBuilder client = ProcessTools.createJavaProcessBuilder( ProcessBuilder client = ProcessTools.createJavaProcessBuilder(
@ -137,7 +137,7 @@ public class LocalManagementTest {
TEST_CLASSPATH, TEST_CLASSPATH,
"--add-exports", "jdk.management.agent/jdk.internal.agent=ALL-UNNAMED", "--add-exports", "jdk.management.agent/jdk.internal.agent=ALL-UNNAMED",
"TestManager", "TestManager",
String.valueOf(serverPrc.getPid()), String.valueOf(serverPrc.pid()),
port.get(), port.get(),
"true" "true"
); );

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -346,7 +346,7 @@ public class JMXStartStopTest {
throw new BindException("Starting process failed due to " + throw new BindException("Starting process failed due to " +
"the requested port not being available"); "the requested port not being available");
} }
pid = p.getPid(); pid = p.pid();
} catch (TimeoutException e) { } catch (TimeoutException e) {
if (p != null) { if (p != null) {
p.destroy(); p.destroy();

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -141,7 +141,7 @@ public class LingeredApp {
if (appProcess == null) { if (appProcess == null) {
throw new RuntimeException("Process is not alive"); throw new RuntimeException("Process is not alive");
} }
return appProcess.getPid(); return appProcess.pid();
} }
/** /**

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -36,11 +36,8 @@
import jdk.testlibrary.ProcessTools; import jdk.testlibrary.ProcessTools;
import jdk.testlibrary.JDKToolLauncher; import jdk.testlibrary.JDKToolLauncher;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class JStatInterval { public class JStatInterval {
private static final String READY = "READY"; private static final String READY = "READY";
@ -88,7 +85,7 @@ public class JStatInterval {
throw new Error("Unable to start the monitored application."); 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"); JDKToolLauncher l = JDKToolLauncher.createUsingTestJDK("jstat");
l.addToolArg("-compiler"); l.addToolArg("-compiler");
l.addToolArg(pidStr); l.addToolArg(pidStr);