提交 ae1cb491 编写于 作者: V vinnie

Merge

...@@ -217,7 +217,7 @@ SUNWprivate_1.1 { ...@@ -217,7 +217,7 @@ SUNWprivate_1.1 {
Java_java_lang_Throwable_fillInStackTrace; Java_java_lang_Throwable_fillInStackTrace;
Java_java_lang_Throwable_getStackTraceDepth; Java_java_lang_Throwable_getStackTraceDepth;
Java_java_lang_Throwable_getStackTraceElement; Java_java_lang_Throwable_getStackTraceElement;
Java_java_lang_UNIXProcess_initIDs; Java_java_lang_UNIXProcess_init;
Java_java_lang_UNIXProcess_waitForProcessExit; Java_java_lang_UNIXProcess_waitForProcessExit;
Java_java_lang_UNIXProcess_forkAndExec; Java_java_lang_UNIXProcess_forkAndExec;
Java_java_lang_UNIXProcess_destroyProcess; Java_java_lang_UNIXProcess_destroyProcess;
......
...@@ -217,7 +217,7 @@ SUNWprivate_1.1 { ...@@ -217,7 +217,7 @@ SUNWprivate_1.1 {
Java_java_lang_Throwable_fillInStackTrace; Java_java_lang_Throwable_fillInStackTrace;
Java_java_lang_Throwable_getStackTraceDepth; Java_java_lang_Throwable_getStackTraceDepth;
Java_java_lang_Throwable_getStackTraceElement; Java_java_lang_Throwable_getStackTraceElement;
Java_java_lang_UNIXProcess_initIDs; Java_java_lang_UNIXProcess_init;
Java_java_lang_UNIXProcess_waitForProcessExit; Java_java_lang_UNIXProcess_waitForProcessExit;
Java_java_lang_UNIXProcess_forkAndExec; Java_java_lang_UNIXProcess_forkAndExec;
Java_java_lang_UNIXProcess_destroyProcess; Java_java_lang_UNIXProcess_destroyProcess;
......
...@@ -184,7 +184,7 @@ import java.security.PrivilegedAction; ...@@ -184,7 +184,7 @@ import java.security.PrivilegedAction;
for (int i=0; i<markerInterfaces.length; i++) { for (int i=0; i<markerInterfaces.length; i++) {
interfaces[i+1] = markerInterfaces[i].getName().replace('.', '/'); interfaces[i+1] = markerInterfaces[i].getName().replace('.', '/');
} }
cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL, cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC,
lambdaClassName, null, lambdaClassName, null,
NAME_MAGIC_ACCESSOR_IMPL, interfaces); NAME_MAGIC_ACCESSOR_IMPL, interfaces);
......
...@@ -25,12 +25,10 @@ ...@@ -25,12 +25,10 @@
package java.nio.file.attribute; package java.nio.file.attribute;
import java.util.Calendar; import java.time.Instant;
import java.util.GregorianCalendar; import java.time.LocalDateTime;
import java.util.Date; import java.time.ZoneOffset;
import java.util.Formatter; import java.util.Objects;
import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
...@@ -51,42 +49,35 @@ public final class FileTime ...@@ -51,42 +49,35 @@ public final class FileTime
implements Comparable<FileTime> implements Comparable<FileTime>
{ {
/** /**
* The value since the epoch; can be negative. * The unit of granularity to interpret the value. Null if
*/ * this {@code FileTime} is converted from an {@code Instant},
private final long value; * the {@code value} and {@code unit} pair will not be used
* in this scenario.
/**
* The unit of granularity to interpret the value.
*/ */
private final TimeUnit unit; private final TimeUnit unit;
/** /**
* The value return by toString (created lazily) * The value since the epoch; can be negative.
*/ */
private String valueAsString; private final long value;
/** /**
* The value in days and excess nanos (created lazily) * The value as Instant (created lazily, if not from an instant)
*/ */
private DaysAndNanos daysAndNanos; private Instant instant;
/** /**
* Returns a DaysAndNanos object representing the value. * The value return by toString (created lazily)
*/ */
private DaysAndNanos asDaysAndNanos() { private String valueAsString;
if (daysAndNanos == null)
daysAndNanos = new DaysAndNanos(value, unit);
return daysAndNanos;
}
/** /**
* Initializes a new instance of this class. * Initializes a new instance of this class.
*/ */
private FileTime(long value, TimeUnit unit) { private FileTime(long value, TimeUnit unit, Instant instant) {
if (unit == null)
throw new NullPointerException();
this.value = value; this.value = value;
this.unit = unit; this.unit = unit;
this.instant = instant;
} }
/** /**
...@@ -102,7 +93,8 @@ public final class FileTime ...@@ -102,7 +93,8 @@ public final class FileTime
* @return a {@code FileTime} representing the given value * @return a {@code FileTime} representing the given value
*/ */
public static FileTime from(long value, TimeUnit unit) { public static FileTime from(long value, TimeUnit unit) {
return new FileTime(value, unit); Objects.requireNonNull(unit, "unit");
return new FileTime(value, unit, null);
} }
/** /**
...@@ -115,7 +107,22 @@ public final class FileTime ...@@ -115,7 +107,22 @@ public final class FileTime
* @return a {@code FileTime} representing the given value * @return a {@code FileTime} representing the given value
*/ */
public static FileTime fromMillis(long value) { public static FileTime fromMillis(long value) {
return new FileTime(value, TimeUnit.MILLISECONDS); return new FileTime(value, TimeUnit.MILLISECONDS, null);
}
/**
* Returns a {@code FileTime} representing the same point of time value
* on the time-line as the provided {@code Instant} object.
*
* @param instant
* the instant to convert
* @return a {@code FileTime} representing the same point on the time-line
* as the provided instant
* @since 1.8
*/
public static FileTime from(Instant instant) {
Objects.requireNonNull(instant, "instant");
return new FileTime(0, null, instant);
} }
/** /**
...@@ -132,7 +139,22 @@ public final class FileTime ...@@ -132,7 +139,22 @@ public final class FileTime
* since the epoch (1970-01-01T00:00:00Z); can be negative * since the epoch (1970-01-01T00:00:00Z); can be negative
*/ */
public long to(TimeUnit unit) { public long to(TimeUnit unit) {
return unit.convert(this.value, this.unit); Objects.requireNonNull(unit, "unit");
if (this.unit != null) {
return unit.convert(this.value, this.unit);
} else {
long secs = unit.convert(instant.getEpochSecond(), TimeUnit.SECONDS);
if (secs == Long.MIN_VALUE || secs == Long.MAX_VALUE) {
return secs;
}
long nanos = unit.convert(instant.getNano(), TimeUnit.NANOSECONDS);
long r = secs + nanos;
// Math.addExact() variant
if (((secs ^ r) & (nanos ^ r)) < 0) {
return (secs < 0) ? Long.MIN_VALUE : Long.MAX_VALUE;
}
return r;
}
} }
/** /**
...@@ -145,7 +167,110 @@ public final class FileTime ...@@ -145,7 +167,110 @@ public final class FileTime
* @return the value in milliseconds, since the epoch (1970-01-01T00:00:00Z) * @return the value in milliseconds, since the epoch (1970-01-01T00:00:00Z)
*/ */
public long toMillis() { public long toMillis() {
return unit.toMillis(value); if (unit != null) {
return unit.toMillis(value);
} else {
long secs = instant.getEpochSecond();
int nanos = instant.getNano();
// Math.multiplyExact() variant
long r = secs * 1000;
long ax = Math.abs(secs);
if (((ax | 1000) >>> 31 != 0)) {
if ((r / 1000) != secs) {
return (secs < 0) ? Long.MIN_VALUE : Long.MAX_VALUE;
}
}
return r + nanos / 1000_000;
}
}
/**
* Time unit constants for conversion.
*/
private static final long HOURS_PER_DAY = 24L;
private static final long MINUTES_PER_HOUR = 60L;
private static final long SECONDS_PER_MINUTE = 60L;
private static final long SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR;
private static final long SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY;
private static final long MILLIS_PER_SECOND = 1000L;
private static final long MICROS_PER_SECOND = 1000_000L;
private static final long NANOS_PER_SECOND = 1000_000_000L;
private static final int NANOS_PER_MILLI = 1000_000;
private static final int NANOS_PER_MICRO = 1000;
// The epoch second of Instant.MIN.
private static final long MIN_SECOND = -31557014167219200L;
// The epoch second of Instant.MAX.
private static final long MAX_SECOND = 31556889864403199L;
/*
* Scale d by m, checking for overflow.
*/
private static long scale(long d, long m, long over) {
if (d > over) return Long.MAX_VALUE;
if (d < -over) return Long.MIN_VALUE;
return d * m;
}
/**
* Converts this {@code FileTime} object to an {@code Instant}.
*
* <p> The conversion creates an {@code Instant} that represents the
* same point on the time-line as this {@code FileTime}.
*
* <p> {@code FileTime} can store points on the time-line further in the
* future and further in the past than {@code Instant}. Conversion
* from such further time points saturates to {@link Instant.MIN} if
* earlier than {@code Instant.MIN} or {@link Instant.MAX} if later
* than {@code Instant.MAX}.
*
* @return an instant representing the same point on the time-line as
* this {@code FileTime} object
* @since 1.8
*/
public Instant toInstant() {
if (instant == null) {
long secs = 0L;
int nanos = 0;
switch (unit) {
case DAYS:
secs = scale(value, SECONDS_PER_DAY,
Long.MAX_VALUE/SECONDS_PER_DAY);
break;
case HOURS:
secs = scale(value, SECONDS_PER_HOUR,
Long.MAX_VALUE/SECONDS_PER_HOUR);
break;
case MINUTES:
secs = scale(value, SECONDS_PER_MINUTE,
Long.MAX_VALUE/SECONDS_PER_MINUTE);
break;
case SECONDS:
secs = value;
break;
case MILLISECONDS:
secs = Math.floorDiv(value, MILLIS_PER_SECOND);
nanos = (int)Math.floorMod(value, MILLIS_PER_SECOND)
* NANOS_PER_MILLI;
break;
case MICROSECONDS:
secs = Math.floorDiv(value, MICROS_PER_SECOND);
nanos = (int)Math.floorMod(value, MICROS_PER_SECOND)
* NANOS_PER_MICRO;
break;
case NANOSECONDS:
secs = Math.floorDiv(value, NANOS_PER_SECOND);
nanos = (int)Math.floorMod(value, NANOS_PER_SECOND);
break;
default : throw new AssertionError("Unit not handled");
}
if (secs <= MIN_SECOND)
instant = Instant.MIN;
else if (secs >= MAX_SECOND)
instant = Instant.MAX;
else
instant = Instant.ofEpochSecond(secs, nanos);
}
return instant;
} }
/** /**
...@@ -176,8 +301,25 @@ public final class FileTime ...@@ -176,8 +301,25 @@ public final class FileTime
*/ */
@Override @Override
public int hashCode() { public int hashCode() {
// hashcode of days/nanos representation to satisfy contract with equals // hashcode of instant representation to satisfy contract with equals
return asDaysAndNanos().hashCode(); return toInstant().hashCode();
}
private long toDays() {
if (unit != null) {
return unit.toDays(value);
} else {
return TimeUnit.SECONDS.toDays(toInstant().getEpochSecond());
}
}
private long toExcessNanos(long days) {
if (unit != null) {
return unit.toNanos(value - unit.convert(days, TimeUnit.DAYS));
} else {
return TimeUnit.SECONDS.toNanos(toInstant().getEpochSecond()
- TimeUnit.DAYS.toSeconds(days));
}
} }
/** /**
...@@ -194,14 +336,52 @@ public final class FileTime ...@@ -194,14 +336,52 @@ public final class FileTime
@Override @Override
public int compareTo(FileTime other) { public int compareTo(FileTime other) {
// same granularity // same granularity
if (unit == other.unit) { if (unit != null && unit == other.unit) {
return (value < other.value) ? -1 : (value == other.value ? 0 : 1); return Long.compare(value, other.value);
} else { } else {
// compare using days/nanos representation when unit differs // compare using instant representation when unit differs
return asDaysAndNanos().compareTo(other.asDaysAndNanos()); long secs = toInstant().getEpochSecond();
long secsOther = other.toInstant().getEpochSecond();
int cmp = Long.compare(secs, secsOther);
if (cmp != 0) {
return cmp;
}
cmp = Long.compare(toInstant().getNano(), other.toInstant().getNano());
if (cmp != 0) {
return cmp;
}
if (secs != MAX_SECOND && secs != MIN_SECOND) {
return 0;
}
// if both this and other's Instant reps are MIN/MAX,
// use daysSinceEpoch and nanosOfDays, which will not
// saturate during calculation.
long days = toDays();
long daysOther = other.toDays();
if (days == daysOther) {
return Long.compare(toExcessNanos(days), other.toExcessNanos(daysOther));
}
return Long.compare(days, daysOther);
} }
} }
// days in a 400 year cycle = 146097
// days in a 10,000 year cycle = 146097 * 25
// seconds per day = 86400
private static final long DAYS_PER_10000_YEARS = 146097L * 25L;
private static final long SECONDS_PER_10000_YEARS = 146097L * 25L * 86400L;
private static final long SECONDS_0000_TO_1970 = ((146097L * 5L) - (30L * 365L + 7L)) * 86400L;
// append year/month/day/hour/minute/second/nano with width and 0 padding
private StringBuilder append(StringBuilder sb, int w, int d) {
while (w > 0) {
sb.append((char)(d/w + '0'));
d = d % w;
w /= 10;
}
return sb;
}
/** /**
* Returns the string representation of this {@code FileTime}. The string * Returns the string representation of this {@code FileTime}. The string
* is returned in the <a * is returned in the <a
...@@ -229,135 +409,67 @@ public final class FileTime ...@@ -229,135 +409,67 @@ public final class FileTime
*/ */
@Override @Override
public String toString() { public String toString() {
String v = valueAsString; if (valueAsString == null) {
if (v == null) { long secs = 0L;
// overflow saturates to Long.MIN_VALUE or Long.MAX_VALUE so this int nanos = 0;
// limits the range: if (instant == null && unit.compareTo(TimeUnit.SECONDS) >= 0) {
// [-292275056-05-16T16:47:04.192Z,292278994-08-17T07:12:55.807Z] secs = unit.toSeconds(value);
long ms = toMillis(); } else {
secs = toInstant().getEpochSecond();
// nothing to do when seconds/minutes/hours/days nanos = toInstant().getNano();
String fractionAsString = "";
if (unit.compareTo(TimeUnit.SECONDS) < 0) {
long fraction = asDaysAndNanos().fractionOfSecondInNanos();
if (fraction != 0L) {
// fraction must be positive
if (fraction < 0L) {
final long MAX_FRACTION_PLUS_1 = 1000L * 1000L * 1000L;
fraction += MAX_FRACTION_PLUS_1;
if (ms != Long.MIN_VALUE) ms--;
}
// convert to String, adding leading zeros as required and
// stripping any trailing zeros
String s = Long.toString(fraction);
int len = s.length();
int width = 9 - len;
StringBuilder sb = new StringBuilder(".");
while (width-- > 0) {
sb.append('0');
}
if (s.charAt(len-1) == '0') {
// drop trailing zeros
len--;
while (s.charAt(len-1) == '0')
len--;
sb.append(s.substring(0, len));
} else {
sb.append(s);
}
fractionAsString = sb.toString();
}
} }
LocalDateTime ldt;
// create calendar to use with formatter. int year = 0;
GregorianCalendar cal = if (secs >= -SECONDS_0000_TO_1970) {
new GregorianCalendar(TimeZone.getTimeZone("UTC"), Locale.ROOT); // current era
if (value < 0L) long zeroSecs = secs - SECONDS_PER_10000_YEARS + SECONDS_0000_TO_1970;
cal.setGregorianChange(new Date(Long.MIN_VALUE)); long hi = Math.floorDiv(zeroSecs, SECONDS_PER_10000_YEARS) + 1;
cal.setTimeInMillis(ms); long lo = Math.floorMod(zeroSecs, SECONDS_PER_10000_YEARS);
ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, nanos, ZoneOffset.UTC);
// years are negative before common era year = ldt.getYear() + (int)hi * 10000;
String sign = (cal.get(Calendar.ERA) == GregorianCalendar.BC) ? "-" : ""; } else {
// before current era
// [-]YYYY-MM-DDThh:mm:ss[.s]Z long zeroSecs = secs + SECONDS_0000_TO_1970;
v = new Formatter(Locale.ROOT) long hi = zeroSecs / SECONDS_PER_10000_YEARS;
.format("%s%tFT%tR:%tS%sZ", sign, cal, cal, cal, fractionAsString) long lo = zeroSecs % SECONDS_PER_10000_YEARS;
.toString(); ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, nanos, ZoneOffset.UTC);
valueAsString = v; year = ldt.getYear() + (int)hi * 10000;
}
return v;
}
/**
* Represents a FileTime's value as two longs: the number of days since
* the epoch, and the excess (in nanoseconds). This is used for comparing
* values with different units of granularity.
*/
private static class DaysAndNanos implements Comparable<DaysAndNanos> {
// constants for conversion
private static final long C0 = 1L;
private static final long C1 = C0 * 24L;
private static final long C2 = C1 * 60L;
private static final long C3 = C2 * 60L;
private static final long C4 = C3 * 1000L;
private static final long C5 = C4 * 1000L;
private static final long C6 = C5 * 1000L;
/**
* The value (in days) since the epoch; can be negative.
*/
private final long days;
/**
* The excess (in nanoseconds); can be negative if days &lt;= 0.
*/
private final long excessNanos;
/**
* Initializes a new instance of this class.
*/
DaysAndNanos(long value, TimeUnit unit) {
long scale;
switch (unit) {
case DAYS : scale = C0; break;
case HOURS : scale = C1; break;
case MINUTES : scale = C2; break;
case SECONDS : scale = C3; break;
case MILLISECONDS : scale = C4; break;
case MICROSECONDS : scale = C5; break;
case NANOSECONDS : scale = C6; break;
default : throw new AssertionError("Unit not handled");
} }
this.days = unit.toDays(value); if (year <= 0) {
this.excessNanos = unit.toNanos(value - (this.days * scale)); year = year - 1;
} }
int fraction = ldt.getNano();
/** StringBuilder sb = new StringBuilder(64);
* Returns the fraction of a second, in nanoseconds. sb.append(year < 0 ? "-" : "");
*/ year = Math.abs(year);
long fractionOfSecondInNanos() { if (year < 10000) {
return excessNanos % (1000L * 1000L * 1000L); append(sb, 1000, Math.abs(year));
} } else {
sb.append(String.valueOf(year));
@Override }
public boolean equals(Object obj) { sb.append('-');
return (obj instanceof DaysAndNanos) ? append(sb, 10, ldt.getMonthValue());
compareTo((DaysAndNanos)obj) == 0 : false; sb.append('-');
} append(sb, 10, ldt.getDayOfMonth());
sb.append('T');
@Override append(sb, 10, ldt.getHour());
public int hashCode() { sb.append(':');
return (int)(days ^ (days >>> 32) ^ append(sb, 10, ldt.getMinute());
excessNanos ^ (excessNanos >>> 32)); sb.append(':');
} append(sb, 10, ldt.getSecond());
if (fraction != 0) {
@Override sb.append('.');
public int compareTo(DaysAndNanos other) { // adding leading zeros and stripping any trailing zeros
if (this.days != other.days) int w = 100_000_000;
return (this.days < other.days) ? -1 : 1; while (fraction % 10 == 0) {
return (this.excessNanos < other.excessNanos) ? -1 : fraction /= 10;
(this.excessNanos == other.excessNanos) ? 0 : 1; w /= 10;
}
append(sb, w, fraction);
}
sb.append('Z');
valueAsString = sb.toString();
} }
return valueAsString;
} }
} }
/* /*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2013, 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,9 +104,21 @@ public class ArrayList<E> extends AbstractList<E> ...@@ -104,9 +104,21 @@ public class ArrayList<E> extends AbstractList<E>
{ {
private static final long serialVersionUID = 8683452581122892189L; private static final long serialVersionUID = 8683452581122892189L;
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/** /**
* The array buffer into which the elements of the ArrayList are stored. * The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. * The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to
* DEFAULT_CAPACITY when the first element is added.
*/ */
private transient Object[] elementData; private transient Object[] elementData;
...@@ -136,7 +148,8 @@ public class ArrayList<E> extends AbstractList<E> ...@@ -136,7 +148,8 @@ public class ArrayList<E> extends AbstractList<E>
* Constructs an empty list with an initial capacity of ten. * Constructs an empty list with an initial capacity of ten.
*/ */
public ArrayList() { public ArrayList() {
this(10); super();
this.elementData = EMPTY_ELEMENTDATA;
} }
/** /**
...@@ -162,8 +175,7 @@ public class ArrayList<E> extends AbstractList<E> ...@@ -162,8 +175,7 @@ public class ArrayList<E> extends AbstractList<E>
*/ */
public void trimToSize() { public void trimToSize() {
modCount++; modCount++;
int oldCapacity = elementData.length; if (size < elementData.length) {
if (size < oldCapacity) {
elementData = Arrays.copyOf(elementData, size); elementData = Arrays.copyOf(elementData, size);
} }
} }
...@@ -176,12 +188,29 @@ public class ArrayList<E> extends AbstractList<E> ...@@ -176,12 +188,29 @@ public class ArrayList<E> extends AbstractList<E>
* @param minCapacity the desired minimum capacity * @param minCapacity the desired minimum capacity
*/ */
public void ensureCapacity(int minCapacity) { public void ensureCapacity(int minCapacity) {
if (minCapacity > 0) int minExpand = (elementData != EMPTY_ELEMENTDATA)
ensureCapacityInternal(minCapacity); // any size if real element table
? 0
// larger than default for empty table. It's already supposed to be
// at default size.
: DEFAULT_CAPACITY;
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
} }
private void ensureCapacityInternal(int minCapacity) { private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++; modCount++;
// overflow-conscious code // overflow-conscious code
if (minCapacity - elementData.length > 0) if (minCapacity - elementData.length > 0)
grow(minCapacity); grow(minCapacity);
...@@ -450,7 +479,7 @@ public class ArrayList<E> extends AbstractList<E> ...@@ -450,7 +479,7 @@ public class ArrayList<E> extends AbstractList<E>
if (numMoved > 0) if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, System.arraycopy(elementData, index+1, elementData, index,
numMoved); numMoved);
elementData[--size] = null; // Let gc do its work elementData[--size] = null; // clear to let GC do its work
return oldValue; return oldValue;
} }
...@@ -495,7 +524,7 @@ public class ArrayList<E> extends AbstractList<E> ...@@ -495,7 +524,7 @@ public class ArrayList<E> extends AbstractList<E>
if (numMoved > 0) if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, System.arraycopy(elementData, index+1, elementData, index,
numMoved); numMoved);
elementData[--size] = null; // Let gc do its work elementData[--size] = null; // clear to let GC do its work
} }
/** /**
...@@ -505,7 +534,7 @@ public class ArrayList<E> extends AbstractList<E> ...@@ -505,7 +534,7 @@ public class ArrayList<E> extends AbstractList<E>
public void clear() { public void clear() {
modCount++; modCount++;
// Let gc do its work // clear to let GC do its work
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
elementData[i] = null; elementData[i] = null;
...@@ -586,10 +615,12 @@ public class ArrayList<E> extends AbstractList<E> ...@@ -586,10 +615,12 @@ public class ArrayList<E> extends AbstractList<E>
System.arraycopy(elementData, toIndex, elementData, fromIndex, System.arraycopy(elementData, toIndex, elementData, fromIndex,
numMoved); numMoved);
// Let gc do its work // clear to let GC do its work
int newSize = size - (toIndex-fromIndex); int newSize = size - (toIndex-fromIndex);
while (size != newSize) for (int i = newSize; i < size; i++) {
elementData[--size] = null; elementData[i] = null;
}
size = newSize;
} }
/** /**
...@@ -677,6 +708,7 @@ public class ArrayList<E> extends AbstractList<E> ...@@ -677,6 +708,7 @@ public class ArrayList<E> extends AbstractList<E>
w += size - r; w += size - r;
} }
if (w != size) { if (w != size) {
// clear to let GC do its work
for (int i = w; i < size; i++) for (int i = w; i < size; i++)
elementData[i] = null; elementData[i] = null;
modCount += size - w; modCount += size - w;
...@@ -701,17 +733,17 @@ public class ArrayList<E> extends AbstractList<E> ...@@ -701,17 +733,17 @@ public class ArrayList<E> extends AbstractList<E>
int expectedModCount = modCount; int expectedModCount = modCount;
s.defaultWriteObject(); s.defaultWriteObject();
// Write out array length // Write out size as capacity for behavioural compatibility with clone()
s.writeInt(elementData.length); s.writeInt(size);
// Write out all elements in the proper order. // Write out all elements in the proper order.
for (int i=0; i<size; i++) for (int i=0; i<size; i++) {
s.writeObject(elementData[i]); s.writeObject(elementData[i]);
}
if (modCount != expectedModCount) { if (modCount != expectedModCount) {
throw new ConcurrentModificationException(); throw new ConcurrentModificationException();
} }
} }
/** /**
...@@ -720,16 +752,24 @@ public class ArrayList<E> extends AbstractList<E> ...@@ -720,16 +752,24 @@ public class ArrayList<E> extends AbstractList<E>
*/ */
private void readObject(java.io.ObjectInputStream s) private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException { throws java.io.IOException, ClassNotFoundException {
elementData = EMPTY_ELEMENTDATA;
// Read in size, and any hidden stuff // Read in size, and any hidden stuff
s.defaultReadObject(); s.defaultReadObject();
// Read in array length and allocate array // Read in capacity
int arrayLength = s.readInt(); s.readInt(); // ignored
Object[] a = elementData = new Object[arrayLength];
if (size > 0) {
// be like clone(), allocate array based upon size not capacity
ensureCapacityInternal(size);
// Read in all elements in the proper order. Object[] a = elementData;
for (int i=0; i<size; i++) // Read in all elements in the proper order.
a[i] = s.readObject(); for (int i=0; i<size; i++) {
a[i] = s.readObject();
}
}
} }
/** /**
......
...@@ -261,6 +261,7 @@ public class Comparators { ...@@ -261,6 +261,7 @@ public class Comparators {
* according to the supplied {@code Comparator} * according to the supplied {@code Comparator}
*/ */
public static<T> BinaryOperator<T> lesserOf(Comparator<? super T> comparator) { public static<T> BinaryOperator<T> lesserOf(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> comparator.compare(a, b) <= 0 ? a : b; return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
} }
...@@ -274,6 +275,7 @@ public class Comparators { ...@@ -274,6 +275,7 @@ public class Comparators {
* according to the supplied {@code Comparator} * according to the supplied {@code Comparator}
*/ */
public static<T> BinaryOperator<T> greaterOf(Comparator<? super T> comparator) { public static<T> BinaryOperator<T> greaterOf(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> comparator.compare(a, b) >= 0 ? a : b; return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
} }
} }
...@@ -129,7 +129,7 @@ public class HashMap<K,V> ...@@ -129,7 +129,7 @@ public class HashMap<K,V>
/** /**
* The default initial capacity - MUST be a power of two. * The default initial capacity - MUST be a power of two.
*/ */
static final int DEFAULT_INITIAL_CAPACITY = 16; static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
/** /**
* The maximum capacity, used if a higher value is implicitly specified * The maximum capacity, used if a higher value is implicitly specified
...@@ -143,10 +143,15 @@ public class HashMap<K,V> ...@@ -143,10 +143,15 @@ public class HashMap<K,V>
*/ */
static final float DEFAULT_LOAD_FACTOR = 0.75f; static final float DEFAULT_LOAD_FACTOR = 0.75f;
/**
* An empty table instance to share when the table is not inflated.
*/
static final Entry<?,?>[] EMPTY_TABLE = {};
/** /**
* The table, resized as necessary. Length MUST Always be a power of two. * The table, resized as necessary. Length MUST Always be a power of two.
*/ */
transient Entry<?,?>[] table; transient Entry<?,?>[] table = EMPTY_TABLE;
/** /**
* The number of key-value mappings contained in this map. * The number of key-value mappings contained in this map.
...@@ -157,6 +162,8 @@ public class HashMap<K,V> ...@@ -157,6 +162,8 @@ public class HashMap<K,V>
* The next size value at which to resize (capacity * load factor). * The next size value at which to resize (capacity * load factor).
* @serial * @serial
*/ */
// If table == EMPTY_TABLE then this is the initial capacity at which the
// table will be created when inflated.
int threshold; int threshold;
/** /**
...@@ -223,14 +230,8 @@ public class HashMap<K,V> ...@@ -223,14 +230,8 @@ public class HashMap<K,V>
throw new IllegalArgumentException("Illegal load factor: " + throw new IllegalArgumentException("Illegal load factor: " +
loadFactor); loadFactor);
// Find a power of 2 >= initialCapacity
int capacity = 1;
while (capacity < initialCapacity)
capacity <<= 1;
this.loadFactor = loadFactor; this.loadFactor = loadFactor;
threshold = (int)Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1); threshold = initialCapacity;
table = new Entry<?,?>[capacity];
init(); init();
} }
...@@ -265,9 +266,33 @@ public class HashMap<K,V> ...@@ -265,9 +266,33 @@ public class HashMap<K,V>
public HashMap(Map<? extends K, ? extends V> m) { public HashMap(Map<? extends K, ? extends V> m) {
this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
inflateTable(threshold);
putAllForCreate(m); putAllForCreate(m);
} }
private static int roundUpToPowerOf2(int number) {
// assert number >= 0 : "number must be non-negative";
int rounded = number >= MAXIMUM_CAPACITY
? MAXIMUM_CAPACITY
: (rounded = Integer.highestOneBit(number)) != 0
? (Integer.bitCount(number) > 1) ? rounded << 1 : rounded
: 1;
return rounded;
}
/**
* Inflates the table.
*/
private void inflateTable(int toSize) {
// Find a power of 2 >= toSize
int capacity = roundUpToPowerOf2(toSize);
threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
table = new Entry[capacity];
}
// internal utilities // internal utilities
/** /**
...@@ -305,6 +330,7 @@ public class HashMap<K,V> ...@@ -305,6 +330,7 @@ public class HashMap<K,V>
* Returns index for hash code h. * Returns index for hash code h.
*/ */
static int indexFor(int h, int length) { static int indexFor(int h, int length) {
// assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
return h & (length-1); return h & (length-1);
} }
...@@ -369,6 +395,10 @@ public class HashMap<K,V> ...@@ -369,6 +395,10 @@ public class HashMap<K,V>
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Entry<K,V> getEntry(Object key) { final Entry<K,V> getEntry(Object key) {
if (isEmpty()) {
return null;
}
int hash = (key == null) ? 0 : hash(key); int hash = (key == null) ? 0 : hash(key);
for (Entry<?,?> e = table[indexFor(hash, table.length)]; for (Entry<?,?> e = table[indexFor(hash, table.length)];
e != null; e != null;
...@@ -381,7 +411,6 @@ public class HashMap<K,V> ...@@ -381,7 +411,6 @@ public class HashMap<K,V>
return null; return null;
} }
/** /**
* Associates the specified value with the specified key in this map. * Associates the specified value with the specified key in this map.
* If the map previously contained a mapping for the key, the old * If the map previously contained a mapping for the key, the old
...@@ -395,6 +424,9 @@ public class HashMap<K,V> ...@@ -395,6 +424,9 @@ public class HashMap<K,V>
* previously associated <tt>null</tt> with <tt>key</tt>.) * previously associated <tt>null</tt> with <tt>key</tt>.)
*/ */
public V put(K key, V value) { public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null) if (key == null)
return putForNullKey(value); return putForNullKey(value);
int hash = hash(key); int hash = hash(key);
...@@ -529,6 +561,10 @@ public class HashMap<K,V> ...@@ -529,6 +561,10 @@ public class HashMap<K,V>
if (numKeysToBeAdded == 0) if (numKeysToBeAdded == 0)
return; return;
if (table == EMPTY_TABLE) {
inflateTable((int) Math.max(numKeysToBeAdded * loadFactor, threshold));
}
/* /*
* Expand the map if the map if the number of mappings to be added * Expand the map if the map if the number of mappings to be added
* is greater than or equal to threshold. This is conservative; the * is greater than or equal to threshold. This is conservative; the
...@@ -573,6 +609,9 @@ public class HashMap<K,V> ...@@ -573,6 +609,9 @@ public class HashMap<K,V>
* for this key. * for this key.
*/ */
final Entry<K,V> removeEntryForKey(Object key) { final Entry<K,V> removeEntryForKey(Object key) {
if (isEmpty()) {
return null;
}
int hash = (key == null) ? 0 : hash(key); int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length); int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
...@@ -605,7 +644,7 @@ public class HashMap<K,V> ...@@ -605,7 +644,7 @@ public class HashMap<K,V>
* for matching. * for matching.
*/ */
final Entry<K,V> removeMapping(Object o) { final Entry<K,V> removeMapping(Object o) {
if (!(o instanceof Map.Entry)) if (isEmpty() || !(o instanceof Map.Entry))
return null; return null;
Map.Entry<?,?> entry = (Map.Entry<?,?>) o; Map.Entry<?,?> entry = (Map.Entry<?,?>) o;
...@@ -641,9 +680,7 @@ public class HashMap<K,V> ...@@ -641,9 +680,7 @@ public class HashMap<K,V>
*/ */
public void clear() { public void clear() {
modCount++; modCount++;
Entry<?,?>[] tab = table; Arrays.fill(table, null);
for (int i = 0; i < tab.length; i++)
tab[i] = null;
size = 0; size = 0;
} }
...@@ -693,7 +730,14 @@ public class HashMap<K,V> ...@@ -693,7 +730,14 @@ public class HashMap<K,V>
} catch (CloneNotSupportedException e) { } catch (CloneNotSupportedException e) {
// assert false; // assert false;
} }
result.table = new Entry<?,?>[table.length]; if (result.table != EMPTY_TABLE) {
result.inflateTable(Math.min(
(int) Math.min(
size * Math.min(1 / loadFactor, 4.0f),
// we have limits...
HashMap.MAXIMUM_CAPACITY),
table.length));
}
result.entrySet = null; result.entrySet = null;
result.modCount = 0; result.modCount = 0;
result.size = 0; result.size = 0;
...@@ -749,8 +793,7 @@ public class HashMap<K,V> ...@@ -749,8 +793,7 @@ public class HashMap<K,V>
} }
public final int hashCode() { public final int hashCode() {
return (key==null ? 0 : key.hashCode()) ^ return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
(value==null ? 0 : value.hashCode());
} }
public final String toString() { public final String toString() {
...@@ -1017,14 +1060,15 @@ public class HashMap<K,V> ...@@ -1017,14 +1060,15 @@ public class HashMap<K,V>
private void writeObject(java.io.ObjectOutputStream s) private void writeObject(java.io.ObjectOutputStream s)
throws IOException throws IOException
{ {
Iterator<Map.Entry<K,V>> i =
(size > 0) ? entrySet0().iterator() : null;
// Write out the threshold, loadfactor, and any hidden stuff // Write out the threshold, loadfactor, and any hidden stuff
s.defaultWriteObject(); s.defaultWriteObject();
// Write out number of buckets // Write out number of buckets
s.writeInt(table.length); if (table==EMPTY_TABLE) {
s.writeInt(roundUpToPowerOf2(threshold));
} else {
s.writeInt(table.length);
}
// Write out size (number of Mappings) // Write out size (number of Mappings)
s.writeInt(size); s.writeInt(size);
...@@ -1049,16 +1093,18 @@ public class HashMap<K,V> ...@@ -1049,16 +1093,18 @@ public class HashMap<K,V>
{ {
// Read in the threshold (ignored), loadfactor, and any hidden stuff // Read in the threshold (ignored), loadfactor, and any hidden stuff
s.defaultReadObject(); s.defaultReadObject();
if (loadFactor <= 0 || Float.isNaN(loadFactor)) if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
throw new InvalidObjectException("Illegal load factor: " + throw new InvalidObjectException("Illegal load factor: " +
loadFactor); loadFactor);
}
// set hashMask // set other fields that need values
Holder.UNSAFE.putIntVolatile(this, Holder.HASHSEED_OFFSET, Holder.UNSAFE.putIntVolatile(this, Holder.HASHSEED_OFFSET,
sun.misc.Hashing.randomHashSeed(this)); sun.misc.Hashing.randomHashSeed(this));
table = EMPTY_TABLE;
// Read in number of buckets and allocate the bucket array; // Read in number of buckets
s.readInt(); // ignored s.readInt(); // ignored.
// Read number of mappings // Read number of mappings
int mappings = s.readInt(); int mappings = s.readInt();
...@@ -1066,23 +1112,21 @@ public class HashMap<K,V> ...@@ -1066,23 +1112,21 @@ public class HashMap<K,V>
throw new InvalidObjectException("Illegal mappings count: " + throw new InvalidObjectException("Illegal mappings count: " +
mappings); mappings);
int initialCapacity = (int) Math.min( // capacity chosen by number of mappings and desired load (if >= 0.25)
// capacity chosen by number of mappings int capacity = (int) Math.min(
// and desired load (if >= 0.25) mappings * Math.min(1 / loadFactor, 4.0f),
mappings * Math.min(1 / loadFactor, 4.0f), // we have limits...
// we have limits... HashMap.MAXIMUM_CAPACITY);
HashMap.MAXIMUM_CAPACITY);
int capacity = 1; // allocate the bucket array;
// find smallest power of two which holds all mappings if (mappings > 0) {
while (capacity < initialCapacity) { inflateTable(capacity);
capacity <<= 1; } else {
threshold = capacity;
} }
table = new Entry<?,?>[capacity];
threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
init(); // Give subclass a chance to do its thing. init(); // Give subclass a chance to do its thing.
// Read the keys and values, and put the mappings in the HashMap // Read the keys and values, and put the mappings in the HashMap
for (int i=0; i<mappings; i++) { for (int i=0; i<mappings; i++) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
......
/* /*
* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2009, 2013, 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
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
package java.util; package java.util;
import java.util.function.Supplier;
/** /**
* This class consists of {@code static} utility methods for operating * This class consists of {@code static} utility methods for operating
* on objects. These utilities include {@code null}-safe or {@code * on objects. These utilities include {@code null}-safe or {@code
...@@ -226,4 +228,30 @@ public final class Objects { ...@@ -226,4 +228,30 @@ public final class Objects {
throw new NullPointerException(message); throw new NullPointerException(message);
return obj; return obj;
} }
/**
* Checks that the specified object reference is not {@code null} and
* throws a customized {@link NullPointerException} if it is.
*
* <p>Unlike the method {@link requireNonNull(Object, String},
* this method allows creation of the message to be deferred until
* after the null check is made. While this may confer a
* performance advantage in the non-null case, when deciding to
* call this method care should be taken that the costs of
* creating the message supplier are less than the cost of just
* creating the string message directly.
*
* @param obj the object reference to check for nullity
* @param messageSupplier supplier of the detail message to be
* used in the event that a {@code NullPointerException} is thrown
* @param <T> the type of the reference
* @return {@code obj} if not {@code null}
* @throws NullPointerException if {@code obj} is {@code null}
* @since 1.8
*/
public static <T> T requireNonNull(T obj, Supplier<String> messageSupplier) {
if (obj == null)
throw new NullPointerException(messageSupplier.get());
return obj;
}
} }
...@@ -466,7 +466,10 @@ public class ZipFileSystem extends FileSystem { ...@@ -466,7 +466,10 @@ public class ZipFileSystem extends FileSystem {
if (eSrc.type == Entry.NEW || eSrc.type == Entry.FILECH) if (eSrc.type == Entry.NEW || eSrc.type == Entry.FILECH)
{ {
u.type = eSrc.type; // make it the same type u.type = eSrc.type; // make it the same type
if (!deletesrc) { // if it's not "rename", just take the data if (deletesrc) { // if it's a "rename", take the data
u.bytes = eSrc.bytes;
u.file = eSrc.file;
} else { // if it's not "rename", copy the data
if (eSrc.bytes != null) if (eSrc.bytes != null)
u.bytes = Arrays.copyOf(eSrc.bytes, eSrc.bytes.length); u.bytes = Arrays.copyOf(eSrc.bytes, eSrc.bytes.length);
else if (eSrc.file != null) { else if (eSrc.file != null) {
...@@ -1118,7 +1121,7 @@ public class ZipFileSystem extends FileSystem { ...@@ -1118,7 +1121,7 @@ public class ZipFileSystem extends FileSystem {
if (old != null) { if (old != null) {
removeFromTree(old); removeFromTree(old);
} }
if (e.type == Entry.NEW || e.type == Entry.FILECH) { if (e.type == Entry.NEW || e.type == Entry.FILECH || e.type == Entry.COPY) {
IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(e.name))); IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(e.name)));
e.sibling = parent.child; e.sibling = parent.child;
parent.child = e; parent.child = e;
...@@ -2326,12 +2329,12 @@ public class ZipFileSystem extends FileSystem { ...@@ -2326,12 +2329,12 @@ public class ZipFileSystem extends FileSystem {
private void removeFromTree(IndexNode inode) { private void removeFromTree(IndexNode inode) {
IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(inode.name))); IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(inode.name)));
IndexNode child = parent.child; IndexNode child = parent.child;
if (child == inode) { if (child.equals(inode)) {
parent.child = child.sibling; parent.child = child.sibling;
} else { } else {
IndexNode last = child; IndexNode last = child;
while ((child = child.sibling) != null) { while ((child = child.sibling) != null) {
if (child == inode) { if (child.equals(inode)) {
last.sibling = child.sibling; last.sibling = child.sibling;
break; break;
} else { } else {
......
...@@ -143,9 +143,9 @@ typedef struct _SurfaceType { ...@@ -143,9 +143,9 @@ typedef struct _SurfaceType {
* structure from the information present in a given Java Composite * structure from the information present in a given Java Composite
* object. * object.
*/ */
typedef JNIEXPORT void (JNICALL CompInfoFunc)(JNIEnv *env, typedef void (JNICALL CompInfoFunc)(JNIEnv *env,
CompositeInfo *pCompInfo, CompositeInfo *pCompInfo,
jobject Composite); jobject Composite);
/* /*
* The additional information needed to implement a primitive that * The additional information needed to implement a primitive that
......
...@@ -94,13 +94,13 @@ typedef struct { ...@@ -94,13 +94,13 @@ typedef struct {
JNIEXPORT void JNICALL nptInitialize JNIEXPORT void JNICALL nptInitialize
(NptEnv **pnpt, char *nptVersion, char *options); (NptEnv **pnpt, char *nptVersion, char *options);
typedef JNIEXPORT void (JNICALL *NptInitialize) typedef void (JNICALL *NptInitialize)
(NptEnv **pnpt, char *nptVersion, char *options); (NptEnv **pnpt, char *nptVersion, char *options);
JNIEXPORT void JNICALL nptTerminate JNIEXPORT void JNICALL nptTerminate
(NptEnv* npt, char *options); (NptEnv* npt, char *options);
typedef JNIEXPORT void (JNICALL *NptTerminate) typedef void (JNICALL *NptTerminate)
(NptEnv* npt, char *options); (NptEnv* npt, char *options);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
......
...@@ -270,11 +270,10 @@ final class UNIXProcess extends Process { ...@@ -270,11 +270,10 @@ final class UNIXProcess extends Process {
return !hasExited; return !hasExited;
} }
/* This routine initializes JNI field offsets for the class */ private static native void init();
private static native void initIDs();
static { static {
initIDs(); init();
} }
/** /**
......
...@@ -270,11 +270,10 @@ final class UNIXProcess extends Process { ...@@ -270,11 +270,10 @@ final class UNIXProcess extends Process {
return !hasExited; return !hasExited;
} }
/* This routine initializes JNI field offsets for the class */ private static native void init();
private static native void initIDs();
static { static {
initIDs(); init();
} }
/** /**
......
...@@ -328,10 +328,9 @@ final class UNIXProcess extends Process { ...@@ -328,10 +328,9 @@ final class UNIXProcess extends Process {
} }
/* This routine initializes JNI field offsets for the class */ private static native void init();
private static native void initIDs();
static { static {
initIDs(); init();
} }
} }
...@@ -26,8 +26,17 @@ ...@@ -26,8 +26,17 @@
#ifndef _JAVASOFT_JNI_MD_H_ #ifndef _JAVASOFT_JNI_MD_H_
#define _JAVASOFT_JNI_MD_H_ #define _JAVASOFT_JNI_MD_H_
#define JNIEXPORT #ifndef __has_attribute
#define JNIIMPORT #define __has_attribute(x) 0
#endif
#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
#define JNIEXPORT __attribute__((visibility("default")))
#define JNIIMPORT __attribute__((visibility("default")))
#else
#define JNIEXPORT
#define JNIIMPORT
#endif
#define JNICALL #define JNICALL
typedef int jint; typedef int jint;
......
...@@ -31,21 +31,24 @@ ...@@ -31,21 +31,24 @@
#ifdef __APPLE__ #ifdef __APPLE__
#include <crt_externs.h> #include <crt_externs.h>
#define environ (*_NSGetEnviron()) #define environ (*_NSGetEnviron())
#else
/* This is one of the rare times it's more portable to declare an
* external symbol explicitly, rather than via a system header.
* The declaration is standardized as part of UNIX98, but there is
* no standard (not even de-facto) header file where the
* declaration is to be found. See:
* http://www.opengroup.org/onlinepubs/009695399/functions/environ.html
* http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html
*
* "All identifiers in this volume of IEEE Std 1003.1-2001, except
* environ, are defined in at least one of the headers" (!)
*/
extern char **environ;
#endif #endif
JNIEXPORT jobjectArray JNICALL JNIEXPORT jobjectArray JNICALL
Java_java_lang_ProcessEnvironment_environ(JNIEnv *env, jclass ign) Java_java_lang_ProcessEnvironment_environ(JNIEnv *env, jclass ign)
{ {
/* This is one of the rare times it's more portable to declare an
* external symbol explicitly, rather than via a system header.
* The declaration is standardized as part of UNIX98, but there is
* no standard (not even de-facto) header file where the
* declaration is to be found. See:
* http://www.opengroup.org/onlinepubs/007908799/xbd/envvar.html */
#ifndef __APPLE__
extern char ** environ; /* environ[i] looks like: VAR=VALUE\0 */
#endif
jsize count = 0; jsize count = 0;
jsize i, j; jsize i, j;
jobjectArray result; jobjectArray result;
......
...@@ -52,6 +52,19 @@ ...@@ -52,6 +52,19 @@
#ifdef __APPLE__ #ifdef __APPLE__
#include <crt_externs.h> #include <crt_externs.h>
#define environ (*_NSGetEnviron()) #define environ (*_NSGetEnviron())
#else
/* This is one of the rare times it's more portable to declare an
* external symbol explicitly, rather than via a system header.
* The declaration is standardized as part of UNIX98, but there is
* no standard (not even de-facto) header file where the
* declaration is to be found. See:
* http://www.opengroup.org/onlinepubs/009695399/functions/environ.html
* http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html
*
* "All identifiers in this volume of IEEE Std 1003.1-2001, except
* environ, are defined in at least one of the headers" (!)
*/
extern char **environ;
#endif #endif
/* /*
...@@ -152,19 +165,6 @@ ...@@ -152,19 +165,6 @@
} while((_result == -1) && (errno == EINTR)); \ } while((_result == -1) && (errno == EINTR)); \
} while(0) } while(0)
/* This is one of the rare times it's more portable to declare an
* external symbol explicitly, rather than via a system header.
* The declaration is standardized as part of UNIX98, but there is
* no standard (not even de-facto) header file where the
* declaration is to be found. See:
* http://www.opengroup.org/onlinepubs/009695399/functions/environ.html
* http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html
*
* "All identifiers in this volume of IEEE Std 1003.1-2001, except
* environ, are defined in at least one of the headers" (!)
*/
extern char **environ;
static void static void
setSIGCHLDHandler(JNIEnv *env) setSIGCHLDHandler(JNIEnv *env)
...@@ -241,52 +241,41 @@ countOccurrences(const char *s, char c) ...@@ -241,52 +241,41 @@ countOccurrences(const char *s, char c)
} }
static const char * const * static const char * const *
splitPath(JNIEnv *env, const char *path) effectivePathv(JNIEnv *env)
{ {
const char *p, *q; char *p;
char **pathv;
int i; int i;
const char *path = effectivePath();
int count = countOccurrences(path, ':') + 1; int count = countOccurrences(path, ':') + 1;
size_t pathvsize = sizeof(const char *) * (count+1);
pathv = NEW(char*, count+1); size_t pathsize = strlen(path) + 1;
pathv[count] = NULL; const char **pathv = (const char **) xmalloc(env, pathvsize + pathsize);
for (p = path, i = 0; i < count; i++, p = q + 1) {
for (q = p; (*q != ':') && (*q != '\0'); q++) if (pathv == NULL)
; return NULL;
if (q == p) /* empty PATH component => "." */ p = (char *) pathv + pathvsize;
pathv[i] = "./"; memcpy(p, path, pathsize);
else { /* split PATH by replacing ':' with NULs; empty components => "." */
int addSlash = ((*(q - 1)) != '/'); for (i = 0; i < count; i++) {
pathv[i] = NEW(char, q - p + addSlash + 1); char *q = p + strcspn(p, ":");
memcpy(pathv[i], p, q - p); pathv[i] = (p == q) ? "." : p;
if (addSlash) *q = '\0';
pathv[i][q - p] = '/'; p = q + 1;
pathv[i][q - p + addSlash] = '\0';
}
} }
return (const char * const *) pathv; pathv[count] = NULL;
return pathv;
} }
/** /**
* Cached value of JVM's effective PATH. * The cached and split version of the JDK's effective PATH.
* (We don't support putenv("PATH=...") in native code) * (We don't support putenv("PATH=...") in native code)
*/ */
static const char *parentPath;
/**
* Split, canonicalized version of parentPath
*/
static const char * const *parentPathv; static const char * const *parentPathv;
static jfieldID field_exitcode;
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_java_lang_UNIXProcess_initIDs(JNIEnv *env, jclass clazz) Java_java_lang_UNIXProcess_init(JNIEnv *env, jclass clazz)
{ {
field_exitcode = (*env)->GetFieldID(env, clazz, "exitcode", "I"); parentPathv = effectivePathv(env);
parentPath = effectivePath();
parentPathv = splitPath(env, parentPath);
setSIGCHLDHandler(env); setSIGCHLDHandler(env);
} }
...@@ -486,6 +475,9 @@ throwIOException(JNIEnv *env, int errnum, const char *defaultDetail) ...@@ -486,6 +475,9 @@ throwIOException(JNIEnv *env, int errnum, const char *defaultDetail)
} }
/* ASCII Decimal representation uses 2.4 times as many bits as binary. */ /* ASCII Decimal representation uses 2.4 times as many bits as binary. */
errmsg = NEW(char, strlen(format) + strlen(detail) + 3 * sizeof(errnum)); errmsg = NEW(char, strlen(format) + strlen(detail) + 3 * sizeof(errnum));
if (errmsg == NULL)
return;
sprintf(errmsg, format, errnum, detail); sprintf(errmsg, format, errnum, detail);
s = JNU_NewStringPlatform(env, errmsg); s = JNU_NewStringPlatform(env, errmsg);
if (s != NULL) { if (s != NULL) {
...@@ -590,11 +582,13 @@ JDK_execvpe(const char *file, ...@@ -590,11 +582,13 @@ JDK_execvpe(const char *file,
for (dirs = parentPathv; *dirs; dirs++) { for (dirs = parentPathv; *dirs; dirs++) {
const char * dir = *dirs; const char * dir = *dirs;
int dirlen = strlen(dir); int dirlen = strlen(dir);
if (filelen + dirlen + 1 >= PATH_MAX) { if (filelen + dirlen + 2 >= PATH_MAX) {
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
continue; continue;
} }
memcpy(expanded_file, dir, dirlen); memcpy(expanded_file, dir, dirlen);
if (expanded_file[dirlen - 1] != '/')
expanded_file[dirlen++] = '/';
memcpy(expanded_file + dirlen, file, filelen); memcpy(expanded_file + dirlen, file, filelen);
expanded_file[dirlen + filelen] = '\0'; expanded_file[dirlen + filelen] = '\0';
execve_with_shell_fallback(expanded_file, argv, envp); execve_with_shell_fallback(expanded_file, argv, envp);
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
static void *awtHandle = NULL; static void *awtHandle = NULL;
typedef JNIEXPORT jint JNICALL JNI_OnLoad_type(JavaVM *vm, void *reserved); typedef jint JNICALL JNI_OnLoad_type(JavaVM *vm, void *reserved);
/* Initialize the Java VM instance variable when the library is /* Initialize the Java VM instance variable when the library is
first loaded */ first loaded */
...@@ -206,7 +206,7 @@ Java_sun_awt_motif_XsessionWMcommand(JNIEnv *env, jobject this, ...@@ -206,7 +206,7 @@ Java_sun_awt_motif_XsessionWMcommand(JNIEnv *env, jobject this,
jobject frame, jstring jcommand) jobject frame, jstring jcommand)
{ {
/* type of the old backdoor function */ /* type of the old backdoor function */
typedef JNIEXPORT void JNICALL typedef void JNICALL
XsessionWMcommand_type(JNIEnv *env, jobject this, XsessionWMcommand_type(JNIEnv *env, jobject this,
jobject frame, jstring jcommand); jobject frame, jstring jcommand);
...@@ -234,7 +234,7 @@ Java_sun_awt_motif_XsessionWMcommand(JNIEnv *env, jobject this, ...@@ -234,7 +234,7 @@ Java_sun_awt_motif_XsessionWMcommand(JNIEnv *env, jobject this,
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_sun_awt_motif_XsessionWMcommand_New(JNIEnv *env, jobjectArray jargv) Java_sun_awt_motif_XsessionWMcommand_New(JNIEnv *env, jobjectArray jargv)
{ {
typedef JNIEXPORT void JNICALL typedef void JNICALL
XsessionWMcommand_New_type(JNIEnv *env, jobjectArray jargv); XsessionWMcommand_New_type(JNIEnv *env, jobjectArray jargv);
static XsessionWMcommand_New_type *XsessionWMcommand = NULL; static XsessionWMcommand_New_type *XsessionWMcommand = NULL;
......
...@@ -138,14 +138,31 @@ public class ZipFSTester { ...@@ -138,14 +138,31 @@ public class ZipFSTester {
Path dst3 = Paths.get(tmpName + "_Tmp"); Path dst3 = Paths.get(tmpName + "_Tmp");
Files.move(dst2, dst3); Files.move(dst2, dst3);
checkEqual(src, dst3); checkEqual(src, dst3);
if (Files.exists(dst2))
throw new RuntimeException("Failed!");
// copyback + move
Files.copy(dst3, dst);
Path dst4 = getPathWithParents(fs, tmpName + "_Tmp0");
Files.move(dst, dst4);
checkEqual(src, dst4);
// delete // delete
if (Files.exists(dst2)) Files.delete(dst4);
if (Files.exists(dst4))
throw new RuntimeException("Failed!"); throw new RuntimeException("Failed!");
Files.delete(dst3); Files.delete(dst3);
if (Files.exists(dst3)) if (Files.exists(dst3))
throw new RuntimeException("Failed!"); throw new RuntimeException("Failed!");
// move (existing entry)
Path dst5 = fs.getPath("META-INF/MANIFEST.MF");
if (Files.exists(dst5)) {
Path dst6 = fs.getPath("META-INF/MANIFEST.MF_TMP");
Files.move(dst5, dst6);
walk(fs.getPath("/"));
}
// newInputStream on dir // newInputStream on dir
Path parent = dst2.getParent(); Path parent = dst2.getParent();
try { try {
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
# #
# @test # @test
# @bug 6990846 7009092 7009085 7015391 7014948 7005986 7017840 7007596 # @bug 6990846 7009092 7009085 7015391 7014948 7005986 7017840 7007596
# 7157656 # 7157656 8002390
# @summary Test ZipFileSystem demo # @summary Test ZipFileSystem demo
# @build Basic PathOps ZipFSTester # @build Basic PathOps ZipFSTester
# @run shell basic.sh # @run shell basic.sh
......
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8012028
* @summary Generated Lambda implementing class should be final
*/
import java.lang.reflect.Modifier;
import java.io.Serializable;
public class LambdaClassFinal {
interface I {
void m();
}
interface Iser extends Serializable {
void m();
}
static void assertTrue(boolean cond) {
if (!cond)
throw new AssertionError();
}
public static void main(String[] args) throws Exception {
new LambdaClassFinal().test();
}
void test() throws Exception {
I lam = () -> { };
assertTrue((lam.getClass().getModifiers() & Modifier.FINAL) != 0);
Iser slam = () -> { };
assertTrue((slam.getClass().getModifiers() & Modifier.FINAL) != 0);
}
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8008941
* @summary Generated Lambda implementing class should be synthetic
*/
import java.lang.reflect.Modifier;
import java.io.Serializable;
public class LambdaClassSynthetic {
interface I {
void m();
}
interface Iser extends Serializable {
void m();
}
static void assertTrue(boolean cond) {
if (!cond)
throw new AssertionError();
}
public static void main(String[] args) throws Exception {
new LambdaClassFinal().test();
}
void test() throws Exception {
I lam = () -> { };
assertTrue(lam.getClass().isSynthetic());
Iser slam = () -> { };
assertTrue(slam.getClass().isSynthetic());
}
}
...@@ -22,14 +22,17 @@ ...@@ -22,14 +22,17 @@
*/ */
/* @test /* @test
* @bug 6844313 * @bug 6844313 8011647
* @summary Unit test for java.nio.file.FileTime * @summary Unit test for java.nio.file.FileTime
*/ */
import java.nio.file.attribute.FileTime; import java.nio.file.attribute.FileTime;
import java.time.Instant;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.*; import static java.util.concurrent.TimeUnit.*;
import java.util.Random; import java.util.Random;
import java.util.EnumSet;
public class Basic { public class Basic {
...@@ -40,27 +43,59 @@ public class Basic { ...@@ -40,27 +43,59 @@ public class Basic {
long tomorrowInDays = TimeUnit.DAYS.convert(now, MILLISECONDS) + 1; long tomorrowInDays = TimeUnit.DAYS.convert(now, MILLISECONDS) + 1;
long yesterdayInDays = TimeUnit.DAYS.convert(now, MILLISECONDS) - 1; long yesterdayInDays = TimeUnit.DAYS.convert(now, MILLISECONDS) - 1;
Instant nowInstant = Instant.ofEpochMilli(now);
// equals // equals
eq(now, MILLISECONDS, now, MILLISECONDS); eq(now, MILLISECONDS, now, MILLISECONDS);
eq(now, MILLISECONDS, now*1000L, MICROSECONDS); eq(now, MILLISECONDS, now*1000L, MICROSECONDS);
neq(now, MILLISECONDS, 0, MILLISECONDS); neq(now, MILLISECONDS, 0, MILLISECONDS);
neq(now, MILLISECONDS, 0, MICROSECONDS); neq(now, MILLISECONDS, 0, MICROSECONDS);
eq(nowInstant, now, MILLISECONDS);
eq(nowInstant, now*1000L, MICROSECONDS);
neq(nowInstant, 0, MILLISECONDS);
neq(nowInstant, 0, MICROSECONDS);
// compareTo // compareTo
cmp(now, MILLISECONDS, now, MILLISECONDS, 0); cmp(now, MILLISECONDS, now, MILLISECONDS, 0);
cmp(now, MILLISECONDS, now*1000L, MICROSECONDS, 0); cmp(now, MILLISECONDS, now*1000L, MICROSECONDS, 0);
cmp(now, MILLISECONDS, now-1234, MILLISECONDS, 1); cmp(now, MILLISECONDS, now-1234, MILLISECONDS, 1);
cmp(now, MILLISECONDS, now+1234, MILLISECONDS, -1); cmp(now, MILLISECONDS, now+1234, MILLISECONDS, -1);
cmp(tomorrowInDays, DAYS, now, MILLISECONDS, 1); cmp(tomorrowInDays, DAYS, now, MILLISECONDS, 1);
cmp(now, MILLISECONDS, tomorrowInDays, DAYS, -1); cmp(now, MILLISECONDS, tomorrowInDays, DAYS, -1);
cmp(yesterdayInDays, DAYS, now, MILLISECONDS, -1); cmp(yesterdayInDays, DAYS, now, MILLISECONDS, -1);
cmp(now, MILLISECONDS, yesterdayInDays, DAYS, 1); cmp(now, MILLISECONDS, yesterdayInDays, DAYS, 1);
cmp(yesterdayInDays, DAYS, now, MILLISECONDS, -1); cmp(yesterdayInDays, DAYS, now, MILLISECONDS, -1);
cmp(Long.MAX_VALUE, DAYS, Long.MAX_VALUE, NANOSECONDS, 1); cmp(Long.MAX_VALUE, DAYS, Long.MAX_VALUE, NANOSECONDS, 1);
cmp(Long.MAX_VALUE, DAYS, Long.MIN_VALUE, NANOSECONDS, 1); cmp(Long.MAX_VALUE, DAYS, Long.MIN_VALUE, NANOSECONDS, 1);
cmp(Long.MIN_VALUE, DAYS, Long.MIN_VALUE, NANOSECONDS, -1); cmp(Long.MIN_VALUE, DAYS, Long.MIN_VALUE, NANOSECONDS, -1);
cmp(Long.MIN_VALUE, DAYS, Long.MAX_VALUE, NANOSECONDS, -1); cmp(Long.MIN_VALUE, DAYS, Long.MAX_VALUE, NANOSECONDS, -1);
cmp(Instant.MIN, Long.MIN_VALUE, DAYS, 1);
cmp(Instant.MIN, Long.MIN_VALUE, HOURS, 1);
cmp(Instant.MIN, Long.MIN_VALUE, MINUTES, 1);
cmp(Instant.MIN, Long.MIN_VALUE, SECONDS, 1);
cmp(Instant.MIN, Instant.MIN.getEpochSecond() - 1, SECONDS, 1);
cmp(Instant.MIN, Instant.MIN.getEpochSecond() - 100, SECONDS, 1);
cmp(Instant.MIN, Instant.MIN.getEpochSecond(), SECONDS, 0);
cmp(Instant.MAX, Long.MAX_VALUE, DAYS, -1);
cmp(Instant.MAX, Long.MAX_VALUE, HOURS, -1);
cmp(Instant.MAX, Long.MAX_VALUE, MINUTES, -1);
cmp(Instant.MAX, Long.MAX_VALUE, SECONDS, -1);
cmp(Instant.MAX, Instant.MAX.getEpochSecond() + 1, SECONDS, -1);
cmp(Instant.MAX, Instant.MAX.getEpochSecond() + 100, SECONDS, -1);
cmp(Instant.MAX, Instant.MAX.getEpochSecond(), SECONDS, 0);
cmp(nowInstant, now, MILLISECONDS, 0);
cmp(nowInstant, now*1000L, MICROSECONDS, 0);
cmp(nowInstant, now-1234, MILLISECONDS, 1);
cmp(nowInstant, now+1234, MILLISECONDS, -1);
cmp(nowInstant, tomorrowInDays, DAYS, -1);
cmp(nowInstant, yesterdayInDays, DAYS, 1);
// to(TimeUnit) // to(TimeUnit)
to(MILLISECONDS.convert(1, DAYS) - 1, MILLISECONDS); to(MILLISECONDS.convert(1, DAYS) - 1, MILLISECONDS);
to(MILLISECONDS.convert(1, DAYS) + 0, MILLISECONDS); to(MILLISECONDS.convert(1, DAYS) + 0, MILLISECONDS);
...@@ -77,6 +112,64 @@ public class Basic { ...@@ -77,6 +112,64 @@ public class Basic {
to(Long.MAX_VALUE, unit); to(Long.MAX_VALUE, unit);
} }
// toInstant()
int N = 1000;
for (TimeUnit unit : EnumSet.allOf(TimeUnit.class)) {
for (int i = 0; i < N; i++) {
long value = rand.nextLong();
FileTime ft = FileTime.from(value, unit);
Instant instant = ft.toInstant();
if (instant != Instant.MIN && instant != Instant.MAX) {
eqTime(value, unit, instant);
}
}
}
for (TimeUnit unit : EnumSet.allOf(TimeUnit.class)) {
long value = Long.MIN_VALUE;
FileTime ft = FileTime.from(value, unit);
Instant instant = ft.toInstant();
if (unit.compareTo(TimeUnit.SECONDS) < 0) {
eqTime(value, unit, instant);
} else if (!instant.equals(Instant.MIN)) {
throw new RuntimeException("should overflow to MIN");
}
value = Long.MAX_VALUE;
ft = FileTime.from(value, unit);
instant = ft.toInstant();
if (unit.compareTo(TimeUnit.SECONDS) < 0) {
eqTime(value, unit, instant);
} else if (!instant.equals(Instant.MAX)) {
throw new RuntimeException("should overflow to MAX");
}
}
// from(Instant)
final long MAX_SECOND = 31556889864403199L;
for (int i = 0; i < N; i++) {
long v = rand.nextLong();
long secs = v % MAX_SECOND;
Instant instant = Instant.ofEpochSecond(secs, rand.nextInt(1000_000_000));
FileTime ft = FileTime.from(instant);
if (!ft.toInstant().equals(instant) || ft.to(SECONDS) != secs) {
throw new RuntimeException("from(Instant) failed");
}
long millis = v;
instant = Instant.ofEpochMilli(millis);
ft = FileTime.from(instant);
if (!ft.toInstant().equals(instant) ||
ft.toMillis() != instant.toEpochMilli()) {
throw new RuntimeException("from(Instant) failed");
}
long nanos = v;
ft = FileTime.from(nanos, NANOSECONDS);
secs = nanos / 1000_000_000;
nanos = nanos % 1000_000_000;
instant = Instant.ofEpochSecond(secs, nanos);
if (!ft.equals(FileTime.from(instant))) {
throw new RuntimeException("from(Instant) failed");
}
}
// toString // toString
ts(1L, DAYS, "1970-01-02T00:00:00Z"); ts(1L, DAYS, "1970-01-02T00:00:00Z");
ts(1L, HOURS, "1970-01-01T01:00:00Z"); ts(1L, HOURS, "1970-01-01T01:00:00Z");
...@@ -108,11 +201,18 @@ public class Basic { ...@@ -108,11 +201,18 @@ public class Basic {
// NTFS epoch in usec. // NTFS epoch in usec.
ts(-11644473600000000L, MICROSECONDS, "1601-01-01T00:00:00Z"); ts(-11644473600000000L, MICROSECONDS, "1601-01-01T00:00:00Z");
// nulls ts(Instant.MIN, "-1000000001-01-01T00:00:00Z");
ts(Instant.MAX, "1000000000-12-31T23:59:59.999999999Z");
try { try {
FileTime.from(0L, null); FileTime.from(0L, null);
throw new RuntimeException("NullPointerException expected"); throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException npe) { } } catch (NullPointerException npe) { }
try {
FileTime.from(null);
throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException npe) { }
FileTime time = FileTime.fromMillis(now); FileTime time = FileTime.fromMillis(now);
if (time.equals(null)) if (time.equals(null))
throw new RuntimeException("should not be equal to null"); throw new RuntimeException("should not be equal to null");
...@@ -120,6 +220,39 @@ public class Basic { ...@@ -120,6 +220,39 @@ public class Basic {
time.compareTo(null); time.compareTo(null);
throw new RuntimeException("NullPointerException expected"); throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException npe) { } } catch (NullPointerException npe) { }
// Instant + toMilli() overflow
overflow(Long.MAX_VALUE,
FileTime.from(Instant.MAX).toMillis());
overflow(Long.MAX_VALUE,
FileTime.from(Instant.ofEpochSecond(Long.MAX_VALUE / 1000 + 1))
.toMillis());
overflow(Long.MIN_VALUE,
FileTime.from(Instant.MIN).toMillis());
overflow(Long.MIN_VALUE,
FileTime.from(Instant.ofEpochSecond(Long.MIN_VALUE / 1000 - 1))
.toMillis());
// Instant + to(TimeUnit) overflow
overflow(Long.MAX_VALUE,
FileTime.from(Instant.ofEpochSecond(Long.MAX_VALUE / 1000 + 1))
.to(MILLISECONDS));
overflow(Long.MAX_VALUE,
FileTime.from(Instant.ofEpochSecond(Long.MAX_VALUE / 1000,
MILLISECONDS.toNanos(1000)))
.to(MILLISECONDS));
overflow(Long.MIN_VALUE,
FileTime.from(Instant.ofEpochSecond(Long.MIN_VALUE / 1000 - 1))
.to(MILLISECONDS));
overflow(Long.MIN_VALUE,
FileTime.from(Instant.ofEpochSecond(Long.MIN_VALUE / 1000,
-MILLISECONDS.toNanos(1)))
.to(MILLISECONDS));
}
static void overflow(long minmax, long v) {
if (v != minmax)
throw new RuntimeException("saturates to Long.MIN/MAX_VALUE expected");
} }
static void cmp(long v1, TimeUnit u1, long v2, TimeUnit u2, int expected) { static void cmp(long v1, TimeUnit u1, long v2, TimeUnit u2, int expected) {
...@@ -128,6 +261,12 @@ public class Basic { ...@@ -128,6 +261,12 @@ public class Basic {
throw new RuntimeException("unexpected order"); throw new RuntimeException("unexpected order");
} }
static void cmp(Instant ins, long v2, TimeUnit u2, int expected) {
int result = FileTime.from(ins).compareTo(FileTime.from(v2, u2));
if (result != expected)
throw new RuntimeException("unexpected order");
}
static void eq(long v1, TimeUnit u1, long v2, TimeUnit u2) { static void eq(long v1, TimeUnit u1, long v2, TimeUnit u2) {
FileTime t1 = FileTime.from(v1, u1); FileTime t1 = FileTime.from(v1, u1);
FileTime t2 = FileTime.from(v2, u2); FileTime t2 = FileTime.from(v2, u2);
...@@ -137,6 +276,28 @@ public class Basic { ...@@ -137,6 +276,28 @@ public class Basic {
throw new RuntimeException("hashCodes should be equal"); throw new RuntimeException("hashCodes should be equal");
} }
static void eq(Instant ins, long v2, TimeUnit u2) {
FileTime t1 = FileTime.from(ins);
FileTime t2 = FileTime.from(v2, u2);
if (!t1.equals(t2))
throw new RuntimeException("not equal");
if (t1.hashCode() != t2.hashCode())
throw new RuntimeException("hashCodes should be equal");
}
static void eqTime(long value, TimeUnit unit, Instant instant) {
long secs = SECONDS.convert(value, unit);
long nanos = NANOSECONDS.convert(value - unit.convert(secs, SECONDS), unit);
if (nanos < 0) { // normalize nanoOfSecond to positive
secs -= 1;
nanos += 1000_000_000;
}
if (secs != instant.getEpochSecond() || (int)nanos != instant.getNano()) {
System.err.println(" ins=" + instant);
throw new RuntimeException("ft and instant are not the same time point");
}
}
static void neq(long v1, TimeUnit u1, long v2, TimeUnit u2) { static void neq(long v1, TimeUnit u1, long v2, TimeUnit u2) {
FileTime t1 = FileTime.from(v1, u1); FileTime t1 = FileTime.from(v1, u1);
FileTime t2 = FileTime.from(v2, u2); FileTime t2 = FileTime.from(v2, u2);
...@@ -144,6 +305,13 @@ public class Basic { ...@@ -144,6 +305,13 @@ public class Basic {
throw new RuntimeException("should not be equal"); throw new RuntimeException("should not be equal");
} }
static void neq(Instant ins, long v2, TimeUnit u2) {
FileTime t1 = FileTime.from(ins);
FileTime t2 = FileTime.from(v2, u2);
if (t1.equals(t2))
throw new RuntimeException("should not be equal");
}
static void to(long v, TimeUnit unit) { static void to(long v, TimeUnit unit) {
FileTime t = FileTime.from(v, unit); FileTime t = FileTime.from(v, unit);
for (TimeUnit u: TimeUnit.values()) { for (TimeUnit u: TimeUnit.values()) {
...@@ -164,4 +332,14 @@ public class Basic { ...@@ -164,4 +332,14 @@ public class Basic {
throw new RuntimeException(); throw new RuntimeException();
} }
} }
static void ts(Instant instant, String expected) {
String result = FileTime.from(instant).toString();
if (!result.equals(expected)) {
System.err.format("FileTime.from(%s).toString() failed\n", instant);
System.err.format("Expected: %s\n", expected);
System.err.format(" Got: %s\n", result);
throw new RuntimeException();
}
}
} }
...@@ -23,8 +23,8 @@ ...@@ -23,8 +23,8 @@
/* /*
* @test * @test
* @bug 8001667 * @bug 8001667 8010279
* @run testng ComparatorsTest * @run testng BasicTest
*/ */
import java.util.Comparator; import java.util.Comparator;
...@@ -33,6 +33,7 @@ import java.util.AbstractMap; ...@@ -33,6 +33,7 @@ import java.util.AbstractMap;
import java.util.Map; import java.util.Map;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.util.function.BinaryOperator;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.ToIntFunction; import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction; import java.util.function.ToLongFunction;
...@@ -41,12 +42,13 @@ import java.util.function.ToDoubleFunction; ...@@ -41,12 +42,13 @@ import java.util.function.ToDoubleFunction;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertSame; import static org.testng.Assert.assertSame;
import static org.testng.Assert.fail;
/** /**
* Unit tests for helper methods in Comparators * Unit tests for helper methods in Comparators
*/ */
@Test(groups = "unit") @Test(groups = "unit")
public class ComparatorsTest { public class BasicTest {
private static class Thing { private static class Thing {
public final int intField; public final int intField;
public final long longField; public final long longField;
...@@ -95,7 +97,7 @@ public class ComparatorsTest { ...@@ -95,7 +97,7 @@ public class ComparatorsTest {
Thing[] things = new Thing[intValues.length]; Thing[] things = new Thing[intValues.length];
for (int i=0; i<intValues.length; i++) for (int i=0; i<intValues.length; i++)
things[i] = new Thing(intValues[i], 0L, 0.0, null); things[i] = new Thing(intValues[i], 0L, 0.0, null);
Comparator<Thing> comp = Comparators.comparing(new ToIntFunction<ComparatorsTest.Thing>() { Comparator<Thing> comp = Comparators.comparing(new ToIntFunction<BasicTest.Thing>() {
@Override @Override
public int applyAsInt(Thing thing) { public int applyAsInt(Thing thing) {
return thing.getIntField(); return thing.getIntField();
...@@ -109,7 +111,7 @@ public class ComparatorsTest { ...@@ -109,7 +111,7 @@ public class ComparatorsTest {
Thing[] things = new Thing[longValues.length]; Thing[] things = new Thing[longValues.length];
for (int i=0; i<longValues.length; i++) for (int i=0; i<longValues.length; i++)
things[i] = new Thing(0, longValues[i], 0.0, null); things[i] = new Thing(0, longValues[i], 0.0, null);
Comparator<Thing> comp = Comparators.comparing(new ToLongFunction<ComparatorsTest.Thing>() { Comparator<Thing> comp = Comparators.comparing(new ToLongFunction<BasicTest.Thing>() {
@Override @Override
public long applyAsLong(Thing thing) { public long applyAsLong(Thing thing) {
return thing.getLongField(); return thing.getLongField();
...@@ -123,7 +125,7 @@ public class ComparatorsTest { ...@@ -123,7 +125,7 @@ public class ComparatorsTest {
Thing[] things = new Thing[doubleValues.length]; Thing[] things = new Thing[doubleValues.length];
for (int i=0; i<doubleValues.length; i++) for (int i=0; i<doubleValues.length; i++)
things[i] = new Thing(0, 0L, doubleValues[i], null); things[i] = new Thing(0, 0L, doubleValues[i], null);
Comparator<Thing> comp = Comparators.comparing(new ToDoubleFunction<ComparatorsTest.Thing>() { Comparator<Thing> comp = Comparators.comparing(new ToDoubleFunction<BasicTest.Thing>() {
@Override @Override
public double applyAsDouble(Thing thing) { public double applyAsDouble(Thing thing) {
return thing.getDoubleField(); return thing.getDoubleField();
...@@ -350,4 +352,61 @@ public class ComparatorsTest { ...@@ -350,4 +352,61 @@ public class ComparatorsTest {
.apply(people[0], people[1]), .apply(people[0], people[1]),
people[1]); people[1]);
} }
}
\ No newline at end of file public void testNulls() {
try {
Comparators.<String>naturalOrder().compare("abc", (String) null);
fail("expected NPE with naturalOrder");
} catch (NullPointerException npe) {}
try {
Comparators.<String>naturalOrder().compare((String) null, "abc");
fail("expected NPE with naturalOrder");
} catch (NullPointerException npe) {}
try {
Comparators.<String>reverseOrder().compare("abc", (String) null);
fail("expected NPE with naturalOrder");
} catch (NullPointerException npe) {}
try {
Comparators.<String>reverseOrder().compare((String) null, "abc");
fail("expected NPE with naturalOrder");
} catch (NullPointerException npe) {}
try {
Comparator<Map.Entry<String, String>> cmp = Comparators.byKey(null);
fail("byKey(null) should throw NPE");
} catch (NullPointerException npe) {}
try {
Comparator<Map.Entry<String, String>> cmp = Comparators.byValue(null);
fail("byValue(null) should throw NPE");
} catch (NullPointerException npe) {}
try {
Comparator<People> cmp = Comparators.comparing((Function<People, String>) null);
fail("comparing(null) should throw NPE");
} catch (NullPointerException npe) {}
try {
Comparator<People> cmp = Comparators.comparing((ToIntFunction<People>) null);
fail("comparing(null) should throw NPE");
} catch (NullPointerException npe) {}
try {
Comparator<People> cmp = Comparators.comparing((ToLongFunction<People>) null);
fail("comparing(null) should throw NPE");
} catch (NullPointerException npe) {}
try {
Comparator<People> cmp = Comparators.comparing((ToDoubleFunction<People>) null);
fail("comparing(null) should throw NPE");
} catch (NullPointerException npe) {}
try {
BinaryOperator<String> op = Comparators.lesserOf(null);
fail("lesserOf(null) should throw NPE");
} catch (NullPointerException npe) {}
try {
BinaryOperator<String> op = Comparators.greaterOf(null);
fail("lesserOf(null) should throw NPE");
} catch (NullPointerException npe) {}
}
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8011200
* @run testng BasicSerialization
* @summary Ensure Maps can be serialized and deserialized.
* @author Mike Duigou
*/
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ByteArrayInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import org.testng.annotations.Test;
import org.testng.annotations.DataProvider;
import static org.testng.Assert.fail;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertSame;
public class BasicSerialization {
enum IntegerEnum {
e0, e1, e2, e3, e4, e5, e6, e7, e8, e9,
e10, e11, e12, e13, e14, e15, e16, e17, e18, e19,
e20, e21, e22, e23, e24, e25, e26, e27, e28, e29,
e30, e31, e32, e33, e34, e35, e36, e37, e38, e39,
e40, e41, e42, e43, e44, e45, e46, e47, e48, e49,
e50, e51, e52, e53, e54, e55, e56, e57, e58, e59,
e60, e61, e62, e63, e64, e65, e66, e67, e68, e69,
e70, e71, e72, e73, e74, e75, e76, e77, e78, e79,
e80, e81, e82, e83, e84, e85, e86, e87, e88, e89,
e90, e91, e92, e93, e94, e95, e96, e97, e98, e99,
EXTRA_KEY;
public static final int SIZE = values().length;
};
private static final int TEST_SIZE = IntegerEnum.SIZE - 1;
/**
* Realized keys ensure that there is always a hard ref to all test objects.
*/
private static final IntegerEnum[] KEYS = new IntegerEnum[TEST_SIZE];
/**
* Realized values ensure that there is always a hard ref to all test
* objects.
*/
private static final String[] VALUES = new String[TEST_SIZE];
static {
IntegerEnum[] keys = IntegerEnum.values();
for (int each = 0; each < TEST_SIZE; each++) {
KEYS[each] = keys[each];
VALUES[each] = keys[each].name();
}
}
private static final IntegerEnum EXTRA_KEY = IntegerEnum.EXTRA_KEY;
private static final String EXTRA_VALUE = IntegerEnum.EXTRA_KEY.name();
public static <K, V> Map<K, V> mapClone(Map<K, V> map) {
Method cloneMethod;
try {
cloneMethod = map.getClass().getMethod("clone", new Class[]{});
} catch (NoSuchMethodException | SecurityException all) {
cloneMethod = null;
}
if (null != cloneMethod) {
try {
Map<K, V> result = (Map<K, V>)cloneMethod.invoke(map, new Object[]{});
return result;
} catch (Exception all) {
fail("clone() failed " + map.getClass().getSimpleName(), all);
return null;
}
} else {
Constructor<? extends Map> copyConstructor;
try {
copyConstructor = (Constructor<? extends Map>)map.getClass().getConstructor(new Class[]{Map.class});
Map<K, V> result = (Map<K, V>)copyConstructor.newInstance(new Object[]{map});
return result;
} catch (Exception all) {
return serialClone(map);
}
}
}
@Test(dataProvider = "Map<IntegerEnum,String>")
public void testSerialization(String description, Map<IntegerEnum, String> map) {
Object foo = new Object();
Map<IntegerEnum, String> clone = mapClone(map);
Map<IntegerEnum, String> serialClone = serialClone(map);
assertEquals(map, map, description + ":should equal self");
assertEquals(clone, map, description + ":should equal clone");
assertEquals(map, clone, description + ": should equal orginal map");
assertEquals(serialClone, map, description + ": should equal deserialized clone");
assertEquals(map, serialClone, description + ": should equal original map");
assertEquals(serialClone, clone, description + ": deserialized clone should equal clone");
assertEquals(clone, serialClone, description + ": clone should equal deserialized clone");
assertFalse(map.containsKey(EXTRA_KEY), description + ":unexpected key");
assertFalse(clone.containsKey(EXTRA_KEY), description + ":unexpected key");
assertFalse(serialClone.containsKey(EXTRA_KEY), description + ":unexpected key");
map.put(EXTRA_KEY, EXTRA_VALUE);
clone.put(EXTRA_KEY, EXTRA_VALUE);
serialClone.put(EXTRA_KEY, EXTRA_VALUE);
assertTrue(map.containsKey(EXTRA_KEY), description + ":missing key");
assertTrue(clone.containsKey(EXTRA_KEY), description + ":missing key");
assertTrue(serialClone.containsKey(EXTRA_KEY), description + ":missing key");
assertSame(map.get(EXTRA_KEY), EXTRA_VALUE, description + ":wrong value");
assertSame(clone.get(EXTRA_KEY), EXTRA_VALUE, description + ":wrong value");
assertSame(serialClone.get(EXTRA_KEY), EXTRA_VALUE, description + ":wrong value");
assertEquals(map, map, description + ":should equal self");
assertEquals(clone, map, description + ":should equal clone");
assertEquals(map, clone, description + ": should equal orginal map");
assertEquals(serialClone, map, description + ": should equal deserialized clone");
assertEquals(map, serialClone, description + ": should equal original map");
assertEquals(serialClone, clone, description + ": deserialized clone should equal clone");
assertEquals(clone, serialClone, description + ": clone should equal deserialized clone");
}
static byte[] serializedForm(Object obj) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
new ObjectOutputStream(baos).writeObject(obj);
return baos.toByteArray();
} catch (IOException e) {
fail("Unexpected Exception", e);
return null;
}
}
static Object readObject(byte[] bytes) throws IOException, ClassNotFoundException {
InputStream is = new ByteArrayInputStream(bytes);
return new ObjectInputStream(is).readObject();
}
@SuppressWarnings("unchecked")
static <T> T serialClone(T obj) {
try {
return (T)readObject(serializedForm(obj));
} catch (IOException | ClassNotFoundException e) {
fail("Unexpected Exception", e);
return null;
}
}
@DataProvider(name = "Map<IntegerEnum,String>", parallel = true)
private static Iterator<Object[]> makeMaps() {
return Arrays.asList(
// empty
new Object[]{"HashMap", new HashMap()},
new Object[]{"LinkedHashMap", new LinkedHashMap()},
new Object[]{"Collections.checkedMap(HashMap)", Collections.checkedMap(new HashMap(), IntegerEnum.class, String.class)},
new Object[]{"Collections.synchronizedMap(HashMap)", Collections.synchronizedMap(new HashMap())},
// null hostile
new Object[]{"EnumMap", new EnumMap(IntegerEnum.class)},
new Object[]{"Hashtable", new Hashtable()},
new Object[]{"TreeMap", new TreeMap()},
new Object[]{"ConcurrentHashMap", new ConcurrentHashMap()},
new Object[]{"ConcurrentSkipListMap", new ConcurrentSkipListMap()},
new Object[]{"Collections.checkedMap(ConcurrentHashMap)", Collections.checkedMap(new ConcurrentHashMap(), IntegerEnum.class, String.class)},
new Object[]{"Collections.synchronizedMap(EnumMap)", Collections.synchronizedMap(new EnumMap(IntegerEnum.class))},
// filled
new Object[]{"HashMap", fillMap(new HashMap())},
new Object[]{"LinkedHashMap", fillMap(new LinkedHashMap())},
new Object[]{"Collections.checkedMap(HashMap)", Collections.checkedMap(fillMap(new HashMap()), IntegerEnum.class, String.class)},
new Object[]{"Collections.synchronizedMap(HashMap)", Collections.synchronizedMap(fillMap(new HashMap()))},
// null hostile
new Object[]{"EnumMap", fillMap(new EnumMap(IntegerEnum.class))},
new Object[]{"Hashtable", fillMap(new Hashtable())},
new Object[]{"TreeMap", fillMap(new TreeMap())},
new Object[]{"ConcurrentHashMap", fillMap(new ConcurrentHashMap())},
new Object[]{"ConcurrentSkipListMap", fillMap(new ConcurrentSkipListMap())},
new Object[]{"Collections.checkedMap(ConcurrentHashMap)", Collections.checkedMap(fillMap(new ConcurrentHashMap()), IntegerEnum.class, String.class)},
new Object[]{"Collections.synchronizedMap(EnumMap)", Collections.synchronizedMap(fillMap(new EnumMap(IntegerEnum.class)))}).iterator();
}
private static Map<IntegerEnum, String> fillMap(Map<IntegerEnum, String> result) {
for (int each = 0; each < TEST_SIZE; each++) {
result.put(KEYS[each], VALUES[each]);
}
return result;
}
}
/* /*
* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2009, 2013, 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,12 +23,13 @@ ...@@ -23,12 +23,13 @@
/* /*
* @test * @test
* @bug 6797535 6889858 6891113 * @bug 6797535 6889858 6891113 8011800
* @summary Basic tests for methods in java.util.Objects * @summary Basic tests for methods in java.util.Objects
* @author Joseph D. Darcy * @author Joseph D. Darcy
*/ */
import java.util.*; import java.util.*;
import java.util.function.*;
public class BasicObjectsTest { public class BasicObjectsTest {
public static void main(String... args) { public static void main(String... args) {
...@@ -40,7 +41,7 @@ public class BasicObjectsTest { ...@@ -40,7 +41,7 @@ public class BasicObjectsTest {
errors += testToString(); errors += testToString();
errors += testToString2(); errors += testToString2();
errors += testCompare(); errors += testCompare();
errors += testNonNull(); errors += testRequireNonNull();
if (errors > 0 ) if (errors > 0 )
throw new RuntimeException(); throw new RuntimeException();
} }
...@@ -158,49 +159,54 @@ public class BasicObjectsTest { ...@@ -158,49 +159,54 @@ public class BasicObjectsTest {
return errors; return errors;
} }
private static int testNonNull() { private static int testRequireNonNull() {
int errors = 0; int errors = 0;
String s;
// Test 1-arg variant final String RNN_1 = "1-arg requireNonNull";
try { final String RNN_2 = "2-arg requireNonNull";
s = Objects.requireNonNull("pants"); final String RNN_3 = "Supplier requireNonNull";
if (s != "pants") {
System.err.printf("1-arg non-null failed to return its arg");
errors++;
}
} catch (NullPointerException e) {
System.err.printf("1-arg nonNull threw unexpected NPE");
errors++;
}
try { Function<String, String> rnn1 = s -> Objects.requireNonNull(s);
s = Objects.requireNonNull(null); Function<String, String> rnn2 = s -> Objects.requireNonNull(s, "trousers");
System.err.printf("1-arg nonNull failed to throw NPE"); Function<String, String> rnn3 = s -> Objects.requireNonNull(s, () -> "trousers");
errors++;
} catch (NullPointerException e) { errors += testRNN_NonNull(rnn1, RNN_1);
// Expected errors += testRNN_NonNull(rnn2, RNN_2);
} errors += testRNN_NonNull(rnn3, RNN_3);
errors += testRNN_Null(rnn1, RNN_1, null);
errors += testRNN_Null(rnn2, RNN_2, "trousers");
errors += testRNN_Null(rnn3, RNN_3, "trousers");
return errors;
}
// Test 2-arg variant private static int testRNN_NonNull(Function<String, String> testFunc,
String testFuncName) {
int errors = 0;
try { try {
s = Objects.requireNonNull("pants", "trousers"); String s = testFunc.apply("pants");
if (s != "pants") { if (s != "pants") {
System.err.printf("2-arg nonNull failed to return its arg"); System.err.printf(testFuncName + " failed to return its arg");
errors++; errors++;
} }
} catch (NullPointerException e) { } catch (NullPointerException e) {
System.err.printf("2-arg nonNull threw unexpected NPE"); System.err.printf(testFuncName + " threw unexpected NPE");
errors++; errors++;
} }
return errors;
}
private static int testRNN_Null(Function<String, String> testFunc,
String testFuncName,
String expectedMessage) {
int errors = 0;
try { try {
s = Objects.requireNonNull(null, "pantaloons"); String s = testFunc.apply(null);
System.err.printf("2-arg nonNull failed to throw NPE"); System.err.printf(testFuncName + " failed to throw NPE");
errors++; errors++;
} catch (NullPointerException e) { } catch (NullPointerException e) {
if (e.getMessage() != "pantaloons") { if (e.getMessage() != expectedMessage) {
System.err.printf("2-arg nonNull threw NPE w/ bad detail msg"); System.err.printf(testFuncName + " threw NPE w/ bad detail msg");
errors++; errors++;
} }
} }
......
...@@ -486,40 +486,40 @@ public class Basic { ...@@ -486,40 +486,40 @@ public class Basic {
CompletableFuture<Integer> cf1 = supplyAsync(() -> 1); CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
CompletableFuture<Integer> cf2 = supplyAsync(() -> 2); CompletableFuture<Integer> cf2 = supplyAsync(() -> 2);
cf3 = cf1.applyToEither(cf2, (x) -> { check(x == 1 || x == 2); return x; }); cf3 = cf1.applyToEither(cf2, (x) -> { check(x == 1 || x == 2); return x; });
check(cf1.isDone() || cf2.isDone());
checkCompletedNormally(cf3, new Object[] {1, 2}); checkCompletedNormally(cf3, new Object[] {1, 2});
check(cf1.isDone() || cf2.isDone());
cf1 = supplyAsync(() -> 1); cf1 = supplyAsync(() -> 1);
cf2 = supplyAsync(() -> 2); cf2 = supplyAsync(() -> 2);
cf3 = cf1.applyToEitherAsync(cf2, (x) -> { check(x == 1 || x == 2); return x; }); cf3 = cf1.applyToEitherAsync(cf2, (x) -> { check(x == 1 || x == 2); return x; });
check(cf1.isDone() || cf2.isDone());
checkCompletedNormally(cf3, new Object[] {1, 2}); checkCompletedNormally(cf3, new Object[] {1, 2});
check(cf1.isDone() || cf2.isDone());
cf1 = supplyAsync(() -> 1); cf1 = supplyAsync(() -> 1);
cf2 = supplyAsync(() -> 2); cf2 = supplyAsync(() -> 2);
cf3 = cf1.applyToEitherAsync(cf2, (x) -> { check(x == 1 || x == 2); return x; }, executor); cf3 = cf1.applyToEitherAsync(cf2, (x) -> { check(x == 1 || x == 2); return x; }, executor);
check(cf1.isDone() || cf2.isDone());
checkCompletedNormally(cf3, new Object[] {1, 2}); checkCompletedNormally(cf3, new Object[] {1, 2});
check(cf1.isDone() || cf2.isDone());
cf1 = supplyAsync(() -> { throw new RuntimeException(); }); cf1 = supplyAsync(() -> { throw new RuntimeException(); });
cf2 = supplyAsync(() -> 2); cf2 = supplyAsync(() -> 2);
cf3 = cf1.applyToEither(cf2, (x) -> { check(x == 2); return x; }); cf3 = cf1.applyToEither(cf2, (x) -> { check(x == 2); return x; });
check(cf1.isDone() || cf2.isDone());
try { check(cf3.join() == 1); } catch (CompletionException x) { pass(); } try { check(cf3.join() == 1); } catch (CompletionException x) { pass(); }
check(cf3.isDone()); check(cf3.isDone());
check(cf1.isDone() || cf2.isDone());
cf1 = supplyAsync(() -> 1); cf1 = supplyAsync(() -> 1);
cf2 = supplyAsync(() -> { throw new RuntimeException(); }); cf2 = supplyAsync(() -> { throw new RuntimeException(); });
cf3 = cf1.applyToEitherAsync(cf2, (x) -> { check(x == 1); return x; }); cf3 = cf1.applyToEitherAsync(cf2, (x) -> { check(x == 1); return x; });
check(cf1.isDone() || cf2.isDone());
try { check(cf3.join() == 1); } catch (CompletionException x) { pass(); } try { check(cf3.join() == 1); } catch (CompletionException x) { pass(); }
check(cf3.isDone()); check(cf3.isDone());
check(cf1.isDone() || cf2.isDone());
cf1 = supplyAsync(() -> { throw new RuntimeException(); }); cf1 = supplyAsync(() -> { throw new RuntimeException(); });
cf2 = supplyAsync(() -> { throw new RuntimeException(); }); cf2 = supplyAsync(() -> { throw new RuntimeException(); });
cf3 = cf1.applyToEitherAsync(cf2, (x) -> { fail(); return x; }); cf3 = cf1.applyToEitherAsync(cf2, (x) -> { fail(); return x; });
check(cf1.isDone() || cf2.isDone());
checkCompletedExceptionally(cf3); checkCompletedExceptionally(cf3);
check(cf1.isDone() || cf2.isDone());
} catch (Throwable t) { unexpected(t); } } catch (Throwable t) { unexpected(t); }
//---------------------------------------------------------------- //----------------------------------------------------------------
...@@ -531,45 +531,45 @@ public class Basic { ...@@ -531,45 +531,45 @@ public class Basic {
CompletableFuture<Integer> cf1 = supplyAsync(() -> 1); CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
CompletableFuture<Integer> cf2 = supplyAsync(() -> 2); CompletableFuture<Integer> cf2 = supplyAsync(() -> 2);
cf3 = cf1.acceptEither(cf2, (x) -> { check(x == 1 || x == 2); atomicInt.incrementAndGet(); }); cf3 = cf1.acceptEither(cf2, (x) -> { check(x == 1 || x == 2); atomicInt.incrementAndGet(); });
check(cf1.isDone() || cf2.isDone());
checkCompletedNormally(cf3, null); checkCompletedNormally(cf3, null);
check(cf1.isDone() || cf2.isDone());
check(atomicInt.get() == (before + 1)); check(atomicInt.get() == (before + 1));
before = atomicInt.get(); before = atomicInt.get();
cf1 = supplyAsync(() -> 1); cf1 = supplyAsync(() -> 1);
cf2 = supplyAsync(() -> 2); cf2 = supplyAsync(() -> 2);
cf3 = cf1.acceptEitherAsync(cf2, (x) -> { check(x == 1 || x == 2); atomicInt.incrementAndGet(); }); cf3 = cf1.acceptEitherAsync(cf2, (x) -> { check(x == 1 || x == 2); atomicInt.incrementAndGet(); });
check(cf1.isDone() || cf2.isDone());
checkCompletedNormally(cf3, null); checkCompletedNormally(cf3, null);
check(cf1.isDone() || cf2.isDone());
check(atomicInt.get() == (before + 1)); check(atomicInt.get() == (before + 1));
before = atomicInt.get(); before = atomicInt.get();
cf1 = supplyAsync(() -> 1); cf1 = supplyAsync(() -> 1);
cf2 = supplyAsync(() -> 2); cf2 = supplyAsync(() -> 2);
cf3 = cf2.acceptEitherAsync(cf1, (x) -> { check(x == 1 || x == 2); atomicInt.incrementAndGet(); }, executor); cf3 = cf2.acceptEitherAsync(cf1, (x) -> { check(x == 1 || x == 2); atomicInt.incrementAndGet(); }, executor);
check(cf1.isDone() || cf2.isDone());
checkCompletedNormally(cf3, null); checkCompletedNormally(cf3, null);
check(cf1.isDone() || cf2.isDone());
check(atomicInt.get() == (before + 1)); check(atomicInt.get() == (before + 1));
cf1 = supplyAsync(() -> { throw new RuntimeException(); }); cf1 = supplyAsync(() -> { throw new RuntimeException(); });
cf2 = supplyAsync(() -> 2); cf2 = supplyAsync(() -> 2);
cf3 = cf2.acceptEitherAsync(cf1, (x) -> { check(x == 2); }, executor); cf3 = cf2.acceptEitherAsync(cf1, (x) -> { check(x == 2); }, executor);
check(cf1.isDone() || cf2.isDone());
try { check(cf3.join() == null); } catch (CompletionException x) { pass(); } try { check(cf3.join() == null); } catch (CompletionException x) { pass(); }
check(cf3.isDone()); check(cf3.isDone());
check(cf1.isDone() || cf2.isDone());
cf1 = supplyAsync(() -> 1); cf1 = supplyAsync(() -> 1);
cf2 = supplyAsync(() -> { throw new RuntimeException(); }); cf2 = supplyAsync(() -> { throw new RuntimeException(); });
cf3 = cf2.acceptEitherAsync(cf1, (x) -> { check(x == 1); }); cf3 = cf2.acceptEitherAsync(cf1, (x) -> { check(x == 1); });
check(cf1.isDone() || cf2.isDone());
try { check(cf3.join() == null); } catch (CompletionException x) { pass(); } try { check(cf3.join() == null); } catch (CompletionException x) { pass(); }
check(cf3.isDone()); check(cf3.isDone());
check(cf1.isDone() || cf2.isDone());
cf1 = supplyAsync(() -> { throw new RuntimeException(); }); cf1 = supplyAsync(() -> { throw new RuntimeException(); });
cf2 = supplyAsync(() -> { throw new RuntimeException(); }); cf2 = supplyAsync(() -> { throw new RuntimeException(); });
cf3 = cf2.acceptEitherAsync(cf1, (x) -> { fail(); }); cf3 = cf2.acceptEitherAsync(cf1, (x) -> { fail(); });
check(cf1.isDone() || cf2.isDone());
checkCompletedExceptionally(cf3); checkCompletedExceptionally(cf3);
check(cf1.isDone() || cf2.isDone());
} catch (Throwable t) { unexpected(t); } } catch (Throwable t) { unexpected(t); }
//---------------------------------------------------------------- //----------------------------------------------------------------
...@@ -581,50 +581,50 @@ public class Basic { ...@@ -581,50 +581,50 @@ public class Basic {
CompletableFuture<Void> cf1 = runAsync(() -> { }); CompletableFuture<Void> cf1 = runAsync(() -> { });
CompletableFuture<Void> cf2 = runAsync(() -> { }); CompletableFuture<Void> cf2 = runAsync(() -> { });
cf3 = cf1.runAfterEither(cf2, () -> { atomicInt.incrementAndGet(); }); cf3 = cf1.runAfterEither(cf2, () -> { atomicInt.incrementAndGet(); });
check(cf1.isDone() || cf2.isDone());
checkCompletedNormally(cf3, null); checkCompletedNormally(cf3, null);
check(cf1.isDone() || cf2.isDone());
check(atomicInt.get() == (before + 1)); check(atomicInt.get() == (before + 1));
before = atomicInt.get(); before = atomicInt.get();
cf1 = runAsync(() -> { }); cf1 = runAsync(() -> { });
cf2 = runAsync(() -> { }); cf2 = runAsync(() -> { });
cf3 = cf1.runAfterEitherAsync(cf2, () -> { atomicInt.incrementAndGet(); }); cf3 = cf1.runAfterEitherAsync(cf2, () -> { atomicInt.incrementAndGet(); });
check(cf1.isDone() || cf2.isDone());
checkCompletedNormally(cf3, null); checkCompletedNormally(cf3, null);
check(cf1.isDone() || cf2.isDone());
check(atomicInt.get() == (before + 1)); check(atomicInt.get() == (before + 1));
before = atomicInt.get(); before = atomicInt.get();
cf1 = runAsync(() -> { }); cf1 = runAsync(() -> { });
cf2 = runAsync(() -> { }); cf2 = runAsync(() -> { });
cf3 = cf2.runAfterEitherAsync(cf1, () -> { atomicInt.incrementAndGet(); }, executor); cf3 = cf2.runAfterEitherAsync(cf1, () -> { atomicInt.incrementAndGet(); }, executor);
check(cf1.isDone() || cf2.isDone());
checkCompletedNormally(cf3, null); checkCompletedNormally(cf3, null);
check(cf1.isDone() || cf2.isDone());
check(atomicInt.get() == (before + 1)); check(atomicInt.get() == (before + 1));
before = atomicInt.get(); before = atomicInt.get();
cf1 = runAsync(() -> { throw new RuntimeException(); }); cf1 = runAsync(() -> { throw new RuntimeException(); });
cf2 = runAsync(() -> { }); cf2 = runAsync(() -> { });
cf3 = cf2.runAfterEither(cf1, () -> { atomicInt.incrementAndGet(); }); cf3 = cf2.runAfterEither(cf1, () -> { atomicInt.incrementAndGet(); });
check(cf1.isDone() || cf2.isDone());
try { check(cf3.join() == null); } catch (CompletionException x) { pass(); } try { check(cf3.join() == null); } catch (CompletionException x) { pass(); }
check(cf3.isDone()); check(cf3.isDone());
check(cf1.isDone() || cf2.isDone());
check(atomicInt.get() == (before + 1)); check(atomicInt.get() == (before + 1));
before = atomicInt.get(); before = atomicInt.get();
cf1 = runAsync(() -> { }); cf1 = runAsync(() -> { });
cf2 = runAsync(() -> { throw new RuntimeException(); }); cf2 = runAsync(() -> { throw new RuntimeException(); });
cf3 = cf1.runAfterEitherAsync(cf2, () -> { atomicInt.incrementAndGet(); }); cf3 = cf1.runAfterEitherAsync(cf2, () -> { atomicInt.incrementAndGet(); });
check(cf1.isDone() || cf2.isDone());
try { check(cf3.join() == null); } catch (CompletionException x) { pass(); } try { check(cf3.join() == null); } catch (CompletionException x) { pass(); }
check(cf3.isDone()); check(cf3.isDone());
check(cf1.isDone() || cf2.isDone());
check(atomicInt.get() == (before + 1)); check(atomicInt.get() == (before + 1));
before = atomicInt.get(); before = atomicInt.get();
cf1 = runAsync(() -> { throw new RuntimeException(); }); cf1 = runAsync(() -> { throw new RuntimeException(); });
cf2 = runAsync(() -> { throw new RuntimeException(); }); cf2 = runAsync(() -> { throw new RuntimeException(); });
cf3 = cf2.runAfterEitherAsync(cf1, () -> { atomicInt.incrementAndGet(); }, executor); cf3 = cf2.runAfterEitherAsync(cf1, () -> { atomicInt.incrementAndGet(); }, executor);
check(cf1.isDone() || cf2.isDone());
checkCompletedExceptionally(cf3); checkCompletedExceptionally(cf3);
check(cf1.isDone() || cf2.isDone());
check(atomicInt.get() == before); check(atomicInt.get() == before);
} catch (Throwable t) { unexpected(t); } } catch (Throwable t) { unexpected(t); }
...@@ -670,16 +670,16 @@ public class Basic { ...@@ -670,16 +670,16 @@ public class Basic {
//---------------------------------------------------------------- //----------------------------------------------------------------
// anyOf tests // anyOf tests
//---------------------------------------------------------------- //----------------------------------------------------------------
//try { try {
// CompletableFuture<Object> cf3; CompletableFuture<Object> cf3;
// for (int k=0; k < 10; k++){ for (int k=0; k < 10; k++){
// CompletableFuture<Integer> cf1 = supplyAsync(() -> 1); CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
// CompletableFuture<Integer> cf2 = supplyAsync(() -> 2); CompletableFuture<Integer> cf2 = supplyAsync(() -> 2);
// cf3 = CompletableFuture.anyOf(cf1, cf2); cf3 = CompletableFuture.anyOf(cf1, cf2);
// check(cf1.isDone() || cf2.isDone()); checkCompletedNormally(cf3, new Object[] {1, 2});
// checkCompletedNormally(cf3, new Object[] {1, 2}); check(cf1.isDone() || cf2.isDone());
// } }
//} catch (Throwable t) { unexpected(t); } } catch (Throwable t) { unexpected(t); }
//---------------------------------------------------------------- //----------------------------------------------------------------
// allOf tests // allOf tests
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册