Merge
This commit is contained in:
commit
97300d43cd
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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) {
|
||||||
|
@ -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 };
|
||||||
|
@ -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.
|
||||||
*
|
*
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
## JPEG release 6b
|
## Independent JPEG Group: JPEG release 6b
|
||||||
|
|
||||||
### JPEG License
|
### JPEG License
|
||||||
<pre>
|
<pre>
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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() + "]";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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"));
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
165
jdk/test/java/net/httpclient/SmallTimeout.java
Normal file
165
jdk/test/java/net/httpclient/SmallTimeout.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -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();
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
);
|
);
|
||||||
|
@ -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"
|
||||||
);
|
);
|
||||||
|
@ -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();
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user