}.
+ * This is a convenience wrapper for the {@linkplain #loop(MethodHandle[][]) generic loop combinator}.
*
- * This is a convenience wrapper for the
- * {@linkplain MethodHandles#loop(MethodHandle[][]) generic loop combinator}, and the constraints imposed on the {@code body}
- * handle follow directly from those described for the latter.
+ * The iterator itself will be determined by the evaluation of the {@code iterator} handle.
+ * Each value it produces will be stored in a loop iteration variable of type {@code T}.
+ *
+ * If the {@code body} handle returns a non-{@code void} type {@code V}, a leading loop iteration variable
+ * of that type is also present. This variable is initialized using the optional {@code init} handle,
+ * or to the {@linkplain #empty default value} of type {@code V} if that handle is {@code null}.
+ *
+ * In each iteration, the iteration variables are passed to an invocation of the {@code body} handle.
+ * A non-{@code void} value returned from the body (of type {@code V}) updates the leading
+ * iteration variable.
+ * The result of the loop handle execution will be the final {@code V} value of that variable
+ * (or {@code void} if there is no {@code V} variable).
+ *
+ * The following rules hold for the argument handles:
+ * - The {@code body} handle must not be {@code null}; its type must be of the form
+ * {@code (V T A...)V}, where {@code V} is non-{@code void}, or else {@code (T A...)void}.
+ * (In the {@code void} case, we assign the type {@code void} to the name {@code V},
+ * and we will write {@code (V T A...)V} with the understanding that a {@code void} type {@code V}
+ * is quietly dropped from the parameter list, leaving {@code (T A...)V}.)
+ *
- The parameter list {@code (V T A...)} of the body contributes to a list
+ * of types called the internal parameter list.
+ * It will constrain the parameter lists of the other loop parts.
+ *
- As a special case, if the body contributes only {@code V} and {@code T} types,
+ * with no additional {@code A} types, then the internal parameter list is extended by
+ * the argument types {@code A...} of the {@code iterator} handle; if it is {@code null} the
+ * single type {@code Iterable} is added and constitutes the {@code A...} list.
+ *
- If the iteration variable types {@code (V T)} are dropped from the internal parameter list, the resulting shorter
+ * list {@code (A...)} is called the external parameter list.
+ *
- The body return type {@code V}, if non-{@code void}, determines the type of an
+ * additional state variable of the loop.
+ * The body must both accept a leading parameter and return a value of this type {@code V}.
+ *
- If {@code init} is non-{@code null}, it must have return type {@code V}.
+ * Its parameter list (of some form {@code (A*)}) must be
+ * effectively identical
+ * to the external parameter list {@code (A...)}.
+ *
- If {@code init} is {@code null}, the loop variable will be initialized to its
+ * {@linkplain #empty default value}.
+ *
- If the {@code iterator} handle is non-{@code null}, it must have the return
+ * type {@code java.util.Iterator} or a subtype thereof.
+ * The iterator it produces when the loop is executed will be assumed
+ * to yield values which can be converted to type {@code T}.
+ *
- The parameter list of an {@code iterator} that is non-{@code null} (of some form {@code (A*)}) must be
+ * effectively identical to the external parameter list {@code (A...)}.
+ *
- If {@code iterator} is {@code null} it defaults to a method handle which behaves
+ * like {@link java.lang.Iterable#iterator()}. In that case, the internal parameter list
+ * {@code (V T A...)} must have at least one {@code A} type, and the default iterator
+ * handle parameter is adjusted to accept the leading {@code A} type, as if by
+ * the {@link MethodHandle#asType asType} conversion method.
+ * The leading {@code A} type must be {@code Iterable} or a subtype thereof, or an array type.
+ * This conversion step, done at loop construction time, must not throw a {@code WrongMethodTypeException}.
+ *
+ *
+ * The type {@code T} may be either a primitive or reference.
+ * Since type {@code Iterator} is erased in the method handle representation to the raw type {@code Iterator},
+ * the {@code iteratedLoop} combinator adjusts the leading argument type for {@code body} to {@code Object}
+ * as if by the {@link MethodHandle#asType asType} conversion method.
+ * Therefore, if an iterator of the wrong type appears as the loop is executed, runtime exceptions may occur
+ * as the result of dynamic conversions performed by {@link MethodHandle#asType(MethodType)}.
+ *
+ * The resulting loop handle's result type and parameter signature are determined as follows:
+ * - The loop handle's result type is the result type {@code V} of the body.
+ *
- The loop handle's parameter types are the types {@code (A...)},
+ * from the external parameter list.
+ *
*
* Here is pseudocode for the resulting loop handle. In the code, {@code V}/{@code v} represent the type / value of
* the loop variable as well as the result type of the loop; {@code T}/{@code t}, that of the elements of the
- * structure the loop iterates over, and {@code A}/{@code a}, that of the argument passed to the loop.
+ * structure the loop iterates over, and {@code A...}/{@code a...} represent arguments passed to the loop.
*
{@code
- * Iterator iterator(A); // defaults to Iterable::iterator
- * V init(A);
- * V body(T,V,A);
- * V iteratedLoop(A a) {
- * Iterator it = iterator(a);
- * V v = init(a);
+ * Iterator iterator(A...); // defaults to Iterable::iterator
+ * V init(A...);
+ * V body(V,T,A...);
+ * V iteratedLoop(A... a...) {
+ * Iterator it = iterator(a...);
+ * V v = init(a...);
* for (T t : it) {
- * v = body(t, v, a);
+ * v = body(v, t, a...);
* }
* return v;
* }
* }
*
- * The type {@code T} may be either a primitive or reference.
- * Since type {@code Iterator} is erased in the method handle representation to the raw type
- * {@code Iterator}, the {@code iteratedLoop} combinator adjusts the leading argument type for {@code body}
- * to {@code Object} as if by the {@link MethodHandle#asType asType} conversion method.
- * Therefore, if an iterator of the wrong type appears as the loop is executed,
- * runtime exceptions may occur as the result of dynamic conversions performed by {@code asType}.
- *
* @apiNote Example:
*
{@code
- * // reverse a list
- * static List reverseStep(String e, List r, List l) {
+ * // get an iterator from a list
+ * static List reverseStep(List r, String e) {
* r.add(0, e);
* return r;
* }
- * static List newArrayList(List l) { return new ArrayList<>(); }
- * // assume MH_reverseStep, MH_newArrayList are handles to the above methods
+ * static List newArrayList() { return new ArrayList<>(); }
+ * // assume MH_reverseStep and MH_newArrayList are handles to the above methods
* MethodHandle loop = MethodHandles.iteratedLoop(null, MH_newArrayList, MH_reverseStep);
* List list = Arrays.asList("a", "b", "c", "d", "e");
* List reversedList = Arrays.asList("e", "d", "c", "b", "a");
* assertEquals(reversedList, (List) loop.invoke(list));
* }
*
- * @implSpec The implementation of this method is equivalent to (excluding error handling):
+ * @apiNote The implementation of this method can be expressed approximately as follows:
*
{@code
* MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) {
- * // assume MH_next and MH_hasNext are handles to methods of Iterator
- * Class> itype = iterator.type().returnType();
- * Class> ttype = body.type().parameterType(0);
- * MethodHandle returnVar = dropArguments(identity(init.type().returnType()), 0, itype);
+ * // assume MH_next, MH_hasNext, MH_startIter are handles to methods of Iterator/Iterable
+ * Class> returnType = body.type().returnType();
+ * Class> ttype = body.type().parameterType(returnType == void.class ? 0 : 1);
* MethodHandle nextVal = MH_next.asType(MH_next.type().changeReturnType(ttype));
+ * MethodHandle retv = null, step = body, startIter = iterator;
+ * if (returnType != void.class) {
+ * // the simple thing first: in (I V A...), drop the I to get V
+ * retv = dropArguments(identity(returnType), 0, Iterator.class);
+ * // body type signature (V T A...), internal loop types (I V A...)
+ * step = swapArguments(body, 0, 1); // swap V <-> T
+ * }
+ * if (startIter == null) startIter = MH_getIter;
* MethodHandle[]
- * iterVar = {iterator, null, MH_hasNext, returnVar}, // it = iterator(); while (it.hasNext)
- * bodyClause = {init, filterArgument(body, 0, nextVal)}; // v = body(t, v, a);
+ * iterVar = { startIter, null, MH_hasNext, retv }, // it = iterator; while (it.hasNext())
+ * bodyClause = { init, filterArguments(step, 0, nextVal) }; // v = body(v, t, a)
* return loop(iterVar, bodyClause);
* }
* }
*
- * @param iterator a handle to return the iterator to start the loop.
- * The handle must have {@link java.util.Iterator} as its return type.
- * Passing {@code null} will make the loop call {@link Iterable#iterator()} on the first
- * incoming value.
- * @param init initializer for additional loop state. This determines the loop's result type.
- * Passing {@code null} or a {@code void} init function will make the loop's result type
- * {@code void}.
- * @param body the body of the loop, which must not be {@code null}.
- * It must accept an initial {@code T} parameter (for the iterated values), and then any
- * additional loop-local variable plus loop parameters.
+ * @param iterator an optional handle to return the iterator to start the loop.
+ * If non-{@code null}, the handle must return {@link java.util.Iterator} or a subtype.
+ * See above for other constraints.
+ * @param init optional initializer, providing the initial value of the loop variable.
+ * May be {@code null}, implying a default initial value. See above for other constraints.
+ * @param body body of the loop, which may not be {@code null}.
+ * It controls the loop parameters and result type in the standard case (see above for details).
+ * It must accept its own return type (if non-void) plus a {@code T} parameter (for the iterated values),
+ * and may accept any number of additional types.
+ * See above for other constraints.
*
* @return a method handle embodying the iteration loop functionality.
- * @throws IllegalArgumentException if any argument has a type inconsistent with the loop structure
+ * @throws NullPointerException if the {@code body} handle is {@code null}.
+ * @throws IllegalArgumentException if any argument violates the above requirements.
*
* @since 9
*/
public static MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) {
- checkIteratedLoop(iterator, body);
- Class> resultType = init == null ?
- body == null ? void.class : body.type().returnType() :
- init.type().returnType();
- boolean voidResult = resultType == void.class;
+ Class> iterableType = iteratedLoopChecks(iterator, init, body);
+ Class> returnType = body.type().returnType();
+ MethodHandle hasNext = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iteratePred);
+ MethodHandle nextRaw = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iterateNext);
+ MethodHandle startIter;
+ MethodHandle nextVal;
+ {
+ MethodType iteratorType;
+ if (iterator == null) {
+ // derive argument type from body, if available, else use Iterable
+ startIter = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_initIterator);
+ iteratorType = startIter.type().changeParameterType(0, iterableType);
+ } else {
+ // force return type to the internal iterator class
+ iteratorType = iterator.type().changeReturnType(Iterator.class);
+ startIter = iterator;
+ }
+ Class> ttype = body.type().parameterType(returnType == void.class ? 0 : 1);
+ MethodType nextValType = nextRaw.type().changeReturnType(ttype);
- MethodHandle initIterator;
- if (iterator == null) {
- MethodHandle initit = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_initIterator);
- initIterator = initit.asType(initit.type().changeParameterType(0,
- body.type().parameterType(voidResult ? 1 : 2)));
- } else {
- initIterator = iterator.asType(iterator.type().changeReturnType(Iterator.class));
+ // perform the asType transforms under an exception transformer, as per spec.:
+ try {
+ startIter = startIter.asType(iteratorType);
+ nextVal = nextRaw.asType(nextValType);
+ } catch (WrongMethodTypeException ex) {
+ throw new IllegalArgumentException(ex);
+ }
}
- Class> ttype = body.type().parameterType(0);
-
- MethodHandle returnVar =
- dropArguments(voidResult ? zero(void.class) : identity(resultType), 0, Iterator.class);
- MethodHandle initnx = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iterateNext);
- MethodHandle nextVal = initnx.asType(initnx.type().changeReturnType(ttype));
-
- MethodHandle[] iterVar = {initIterator, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iteratePred),
- returnVar};
- MethodHandle[] bodyClause = {init, filterArgument(body, 0, nextVal)};
+ MethodHandle retv = null, step = body;
+ if (returnType != void.class) {
+ // the simple thing first: in (I V A...), drop the I to get V
+ retv = dropArguments(identity(returnType), 0, Iterator.class);
+ // body type signature (V T A...), internal loop types (I V A...)
+ step = swapArguments(body, 0, 1); // swap V <-> T
+ }
+ MethodHandle[]
+ iterVar = { startIter, null, hasNext, retv },
+ bodyClause = { init, filterArgument(step, 0, nextVal) };
return loop(iterVar, bodyClause);
}
+ private static Class> iteratedLoopChecks(MethodHandle iterator, MethodHandle init, MethodHandle body) {
+ Objects.requireNonNull(body);
+ MethodType bodyType = body.type();
+ Class> returnType = bodyType.returnType();
+ List> innerList = bodyType.parameterList();
+ // strip leading V value if present
+ int vsize = (returnType == void.class ? 0 : 1);
+ if (vsize != 0 && (innerList.size() == 0 || innerList.get(0) != returnType)) {
+ // argument list has no "V" => error
+ MethodType expected = bodyType.insertParameterTypes(0, returnType);
+ throw misMatchedTypes("body function", bodyType, expected);
+ } else if (innerList.size() <= vsize) {
+ // missing T type => error
+ MethodType expected = bodyType.insertParameterTypes(vsize, Object.class);
+ throw misMatchedTypes("body function", bodyType, expected);
+ }
+ //Class> elementType = innerList.get(vsize); // do not need this
+ List> outerList = innerList.subList(vsize + 1, innerList.size());
+ if (outerList.isEmpty()) {
+ // special case; take lists from iterator handle
+ outerList = ((iterator != null)
+ ? iterator.type().parameterList()
+ : Arrays.asList(Iterable.class));
+ innerList = bodyType.insertParameterTypes(vsize + 1, outerList).parameterList();
+ }
+ if (iterator != null) {
+ MethodType itype = iterator.type();
+ if (!Iterator.class.isAssignableFrom(itype.returnType())) {
+ throw newIllegalArgumentException("iteratedLoop first argument must have Iterator return type");
+ }
+ if (!itype.effectivelyIdenticalParameters(0, outerList)) {
+ MethodType expected = methodType(itype.returnType(), outerList);
+ throw misMatchedTypes("iterator parameters", itype, expected);
+ }
+ }
+ if (init != null) {
+ MethodType initType = init.type();
+ if (initType.returnType() != returnType ||
+ !initType.effectivelyIdenticalParameters(0, outerList)) {
+ throw misMatchedTypes("loop initializer", initType, methodType(returnType, outerList));
+ }
+ }
+ Class> iterableType = outerList.isEmpty() ? null : outerList.get(0);
+ if (iterableType != null && !Iterable.class.isAssignableFrom(iterableType) && !iterableType.isArray()) {
+ throw newIllegalArgumentException(
+ "inferred first loop argument must be an array or inherit from Iterable: " + iterableType);
+ }
+ return iterableType; // help the caller a bit
+ }
+
+ /*non-public*/ static MethodHandle swapArguments(MethodHandle mh, int i, int j) {
+ // there should be a better way to uncross my wires
+ int arity = mh.type().parameterCount();
+ int[] order = new int[arity];
+ for (int k = 0; k < arity; k++) order[k] = k;
+ order[i] = j; order[j] = i;
+ Class>[] types = mh.type().parameterArray();
+ Class> ti = types[i]; types[i] = types[j]; types[j] = ti;
+ MethodType swapType = methodType(mh.type().returnType(), types);
+ return permuteArguments(mh, swapType, order);
+ }
+
/**
* Makes a method handle that adapts a {@code target} method handle by wrapping it in a {@code try-finally} block.
* Another method handle, {@code cleanup}, represents the functionality of the {@code finally} block. Any exception
@@ -4880,220 +5622,33 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
List> cleanupParamTypes = cleanup.type().parameterList();
Class> rtype = target.type().returnType();
- checkTryFinally(target, cleanup);
+ tryFinallyChecks(target, cleanup);
// Match parameter lists: if the cleanup has a shorter parameter list than the target, add ignored arguments.
// The cleanup parameter list (minus the leading Throwable and result parameters) must be a sublist of the
// target parameter list.
cleanup = dropArgumentsToMatch(cleanup, (rtype == void.class ? 1 : 2), targetParamTypes, 0);
- return MethodHandleImpl.makeTryFinally(target, cleanup, rtype, targetParamTypes);
+ // Use asFixedArity() to avoid unnecessary boxing of last argument for VarargsCollector case.
+ return MethodHandleImpl.makeTryFinally(target.asFixedArity(), cleanup.asFixedArity(), rtype, targetParamTypes);
}
- /**
- * Adapts a target method handle by pre-processing some of its arguments, starting at a given position, and then
- * calling the target with the result of the pre-processing, inserted into the original sequence of arguments just
- * before the folded arguments.
- *
- * This method is closely related to {@link #foldArguments(MethodHandle, MethodHandle)}, but allows to control the
- * position in the parameter list at which folding takes place. The argument controlling this, {@code pos}, is a
- * zero-based index. The aforementioned method {@link #foldArguments(MethodHandle, MethodHandle)} assumes position
- * 0.
- *
- * @apiNote Example:
- *
{@code
- import static java.lang.invoke.MethodHandles.*;
- import static java.lang.invoke.MethodType.*;
- ...
- MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
- "println", methodType(void.class, String.class))
- .bindTo(System.out);
- MethodHandle cat = lookup().findVirtual(String.class,
- "concat", methodType(String.class, String.class));
- assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
- MethodHandle catTrace = foldArguments(cat, 1, trace);
- // also prints "jum":
- assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
- * }
- * Here is pseudocode for the resulting adapter. In the code, {@code T}
- * represents the result type of the {@code target} and resulting adapter.
- * {@code V}/{@code v} represent the type and value of the parameter and argument
- * of {@code target} that precedes the folding position; {@code V} also is
- * the result type of the {@code combiner}. {@code A}/{@code a} denote the
- * types and values of the {@code N} parameters and arguments at the folding
- * position. {@code Z}/{@code z} and {@code B}/{@code b} represent the types
- * and values of the {@code target} parameters and arguments that precede and
- * follow the folded parameters and arguments starting at {@code pos},
- * respectively.
- *
{@code
- * // there are N arguments in A...
- * T target(Z..., V, A[N]..., B...);
- * V combiner(A...);
- * T adapter(Z... z, A... a, B... b) {
- * V v = combiner(a...);
- * return target(z..., v, a..., b...);
- * }
- * // and if the combiner has a void return:
- * T target2(Z..., A[N]..., B...);
- * void combiner2(A...);
- * T adapter2(Z... z, A... a, B... b) {
- * combiner2(a...);
- * return target2(z..., a..., b...);
- * }
- * }
- *
- * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
- * variable-arity method handle}, even if the original target method handle was.
- *
- * @param target the method handle to invoke after arguments are combined
- * @param pos the position at which to start folding and at which to insert the folding result; if this is {@code
- * 0}, the effect is the same as for {@link #foldArguments(MethodHandle, MethodHandle)}.
- * @param combiner method handle to call initially on the incoming arguments
- * @return method handle which incorporates the specified argument folding logic
- * @throws NullPointerException if either argument is null
- * @throws IllegalArgumentException if {@code combiner}'s return type
- * is non-void and not the same as the argument type at position {@code pos} of
- * the target signature, or if the {@code N} argument types at position {@code pos}
- * of the target signature
- * (skipping one matching the {@code combiner}'s return type)
- * are not identical with the argument types of {@code combiner}
- *
- * @see #foldArguments(MethodHandle, MethodHandle)
- * @since 9
- */
- public static MethodHandle foldArguments(MethodHandle target, int pos, MethodHandle combiner) {
- MethodType targetType = target.type();
- MethodType combinerType = combiner.type();
- Class> rtype = foldArgumentChecks(pos, targetType, combinerType);
- BoundMethodHandle result = target.rebind();
- boolean dropResult = rtype == void.class;
- LambdaForm lform = result.editor().foldArgumentsForm(1 + pos, dropResult, combinerType.basicType());
- MethodType newType = targetType;
- if (!dropResult) {
- newType = newType.dropParameterTypes(pos, pos + 1);
- }
- result = result.copyWithExtendL(newType, lform, combiner);
- return result;
- }
-
- /**
- * As {@see foldArguments(MethodHandle, int, MethodHandle)}, but with the
- * added capability of selecting the arguments from the targets parameters
- * to call the combiner with. This allows us to avoid some simple cases of
- * permutations and padding the combiner with dropArguments to select the
- * right argument, which may ultimately produce fewer intermediaries.
- */
- static MethodHandle foldArguments(MethodHandle target, int pos, MethodHandle combiner, int ... argPositions) {
- MethodType targetType = target.type();
- MethodType combinerType = combiner.type();
- Class> rtype = foldArgumentChecks(pos, targetType, combinerType, argPositions);
- BoundMethodHandle result = target.rebind();
- boolean dropResult = rtype == void.class;
- LambdaForm lform = result.editor().foldArgumentsForm(1 + pos, dropResult, combinerType.basicType(), argPositions);
- MethodType newType = targetType;
- if (!dropResult) {
- newType = newType.dropParameterTypes(pos, pos + 1);
- }
- result = result.copyWithExtendL(newType, lform, combiner);
- return result;
- }
-
- private static void checkLoop0(MethodHandle[][] clauses) {
- if (clauses == null || clauses.length == 0) {
- throw newIllegalArgumentException("null or no clauses passed");
- }
- if (Stream.of(clauses).anyMatch(Objects::isNull)) {
- throw newIllegalArgumentException("null clauses are not allowed");
- }
- if (Stream.of(clauses).anyMatch(c -> c.length > 4)) {
- throw newIllegalArgumentException("All loop clauses must be represented as MethodHandle arrays with at most 4 elements.");
- }
- }
-
- private static void checkLoop1a(int i, MethodHandle in, MethodHandle st) {
- if (in.type().returnType() != st.type().returnType()) {
- throw misMatchedTypes("clause " + i + ": init and step return types", in.type().returnType(),
- st.type().returnType());
- }
- }
-
- private static List> buildCommonSuffix(List init, List step, List pred, List fini, int cpSize) {
- final List> empty = List.of();
- final List nonNullInits = init.stream().filter(Objects::nonNull).collect(Collectors.toList());
- if (nonNullInits.isEmpty()) {
- final List> longest = Stream.of(step, pred, fini).flatMap(List::stream).filter(Objects::nonNull).
- // take only those that can contribute to a common suffix because they are longer than the prefix
- map(MethodHandle::type).filter(t -> t.parameterCount() > cpSize).map(MethodType::parameterList).
- reduce((p, q) -> p.size() >= q.size() ? p : q).orElse(empty);
- return longest.size() == 0 ? empty : longest.subList(cpSize, longest.size());
- } else {
- return nonNullInits.stream().map(MethodHandle::type).map(MethodType::parameterList).
- reduce((p, q) -> p.size() >= q.size() ? p : q).get();
- }
- }
-
- private static void checkLoop1b(List init, List> commonSuffix) {
- if (init.stream().filter(Objects::nonNull).map(MethodHandle::type).map(MethodType::parameterList).
- anyMatch(pl -> !pl.equals(commonSuffix.subList(0, pl.size())))) {
- throw newIllegalArgumentException("found non-effectively identical init parameter type lists: " + init +
- " (common suffix: " + commonSuffix + ")");
- }
- }
-
- private static void checkLoop1cd(List pred, List fini, Class> loopReturnType) {
- if (fini.stream().filter(Objects::nonNull).map(MethodHandle::type).map(MethodType::returnType).
- anyMatch(t -> t != loopReturnType)) {
- throw newIllegalArgumentException("found non-identical finalizer return types: " + fini + " (return type: " +
- loopReturnType + ")");
- }
-
- if (!pred.stream().filter(Objects::nonNull).findFirst().isPresent()) {
- throw newIllegalArgumentException("no predicate found", pred);
- }
- if (pred.stream().filter(Objects::nonNull).map(MethodHandle::type).map(MethodType::returnType).
- anyMatch(t -> t != boolean.class)) {
- throw newIllegalArgumentException("predicates must have boolean return type", pred);
- }
- }
-
- private static void checkLoop2(List step, List pred, List fini, List> commonParameterSequence) {
- final int cpSize = commonParameterSequence.size();
- if (Stream.of(step, pred, fini).flatMap(List::stream).filter(Objects::nonNull).map(MethodHandle::type).
- map(MethodType::parameterList).
- anyMatch(pl -> pl.size() > cpSize || !pl.equals(commonParameterSequence.subList(0, pl.size())))) {
- throw newIllegalArgumentException("found non-effectively identical parameter type lists:\nstep: " + step +
- "\npred: " + pred + "\nfini: " + fini + " (common parameter sequence: " + commonParameterSequence + ")");
- }
- }
-
- private static void checkIteratedLoop(MethodHandle iterator, MethodHandle body) {
- if (null != iterator && !Iterator.class.isAssignableFrom(iterator.type().returnType())) {
- throw newIllegalArgumentException("iteratedLoop first argument must have Iterator return type");
- }
- if (null == body) {
- throw newIllegalArgumentException("iterated loop body must not be null");
- }
- }
-
- private static void checkTryFinally(MethodHandle target, MethodHandle cleanup) {
+ private static void tryFinallyChecks(MethodHandle target, MethodHandle cleanup) {
Class> rtype = target.type().returnType();
if (rtype != cleanup.type().returnType()) {
throw misMatchedTypes("target and return types", cleanup.type().returnType(), rtype);
}
- List> cleanupParamTypes = cleanup.type().parameterList();
- if (!Throwable.class.isAssignableFrom(cleanupParamTypes.get(0))) {
+ MethodType cleanupType = cleanup.type();
+ if (!Throwable.class.isAssignableFrom(cleanupType.parameterType(0))) {
throw misMatchedTypes("cleanup first argument and Throwable", cleanup.type(), Throwable.class);
}
- if (rtype != void.class && cleanupParamTypes.get(1) != rtype) {
+ if (rtype != void.class && cleanupType.parameterType(1) != rtype) {
throw misMatchedTypes("cleanup second argument and target return type", cleanup.type(), rtype);
}
// The cleanup parameter list (minus the leading Throwable and result parameters) must be a sublist of the
// target parameter list.
int cleanupArgIndex = rtype == void.class ? 1 : 2;
- List> cleanupArgSuffix = cleanupParamTypes.subList(cleanupArgIndex, cleanupParamTypes.size());
- List> targetParamTypes = target.type().parameterList();
- if (targetParamTypes.size() < cleanupArgSuffix.size() ||
- !cleanupArgSuffix.equals(targetParamTypes.subList(0, cleanupParamTypes.size() - cleanupArgIndex))) {
+ if (!cleanupType.effectivelyIdenticalParameters(cleanupArgIndex, target.type().parameterList())) {
throw misMatchedTypes("cleanup parameters after (Throwable,result) and target parameter list prefix",
cleanup.type(), target.type());
}
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java
index 2022efca753..ffb8a6a7859 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java
@@ -809,6 +809,28 @@ class MethodType implements java.io.Serializable {
return sj.toString();
}
+ /** True if my parameter list is effectively identical to the given full list,
+ * after skipping the given number of my own initial parameters.
+ * In other words, after disregarding {@code skipPos} parameters,
+ * my remaining parameter list is no longer than the {@code fullList}, and
+ * is equal to the same-length initial sublist of {@code fullList}.
+ */
+ /*non-public*/
+ boolean effectivelyIdenticalParameters(int skipPos, List> fullList) {
+ int myLen = ptypes.length, fullLen = fullList.size();
+ if (skipPos > myLen || myLen - skipPos > fullLen)
+ return false;
+ List> myList = Arrays.asList(ptypes);
+ if (skipPos != 0) {
+ myList = myList.subList(skipPos, myLen);
+ myLen -= skipPos;
+ }
+ if (fullLen == myLen)
+ return myList.equals(fullList);
+ else
+ return myList.equals(fullList.subList(0, myLen));
+ }
+
/** True if the old return type can always be viewed (w/o casting) under new return type,
* and the new parameters can be viewed (w/o casting) under the old parameter types.
*/
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java
index db9a3e000b9..1d0e22fec11 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java
@@ -664,7 +664,7 @@ final class ModuleInfo {
try {
bb.get(b, off, len);
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -681,7 +681,7 @@ final class ModuleInfo {
int ch = bb.get();
return (ch != 0);
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -690,7 +690,7 @@ final class ModuleInfo {
try {
return bb.get();
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -699,7 +699,7 @@ final class ModuleInfo {
try {
return ((int) bb.get()) & 0xff;
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -708,7 +708,7 @@ final class ModuleInfo {
try {
return bb.getShort();
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -717,7 +717,7 @@ final class ModuleInfo {
try {
return ((int) bb.getShort()) & 0xffff;
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -726,7 +726,7 @@ final class ModuleInfo {
try {
return bb.getChar();
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -735,7 +735,7 @@ final class ModuleInfo {
try {
return bb.getInt();
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -744,7 +744,7 @@ final class ModuleInfo {
try {
return bb.getLong();
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -753,7 +753,7 @@ final class ModuleInfo {
try {
return bb.getFloat();
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -762,7 +762,7 @@ final class ModuleInfo {
try {
return bb.getDouble();
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java b/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java
index ba2632b5445..15d41a4101d 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java
@@ -597,10 +597,10 @@ public class Proxy implements java.io.Serializable {
private final Module module;
ProxyBuilder(ClassLoader loader, List> interfaces) {
if (!VM.isModuleSystemInited()) {
- throw new InternalError("Proxy is not supported until module system is fully initialzed");
+ throw new InternalError("Proxy is not supported until module system is fully initialized");
}
if (interfaces.size() > 65535) {
- throw new IllegalArgumentException("interface limit exceeded");
+ throw new IllegalArgumentException("interface limit exceeded: " + interfaces.size());
}
Set> refTypes = referencedTypes(loader, interfaces);
diff --git a/jdk/src/java.base/share/classes/java/util/ArrayList.java b/jdk/src/java.base/share/classes/java/util/ArrayList.java
index f5b672aaac1..f48cc43e48c 100644
--- a/jdk/src/java.base/share/classes/java/util/ArrayList.java
+++ b/jdk/src/java.base/share/classes/java/util/ArrayList.java
@@ -876,6 +876,8 @@ public class ArrayList extends AbstractList
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
+ Itr() {}
+
public boolean hasNext() {
return cursor != size;
}
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java
index 5708af2653c..9946b128591 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java
@@ -2559,6 +2559,13 @@ public class CompletableFuture implements Future, CompletionStage {
* exceptionally with a CompletionException with this exception as
* cause.
*
+ * Unless overridden by a subclass, a new non-minimal
+ * CompletableFuture with all methods available can be obtained from
+ * a minimal CompletionStage via {@link #toCompletableFuture()}.
+ * For example, completion of a minimal stage can be awaited by
+ *
+ *
{@code minimalStage.toCompletableFuture().join(); }
+ *
* @return the new CompletionStage
* @since 9
*/
@@ -2853,6 +2860,16 @@ public class CompletableFuture implements Future, CompletionStage {
@Override public CompletableFuture completeOnTimeout
(T value, long timeout, TimeUnit unit) {
throw new UnsupportedOperationException(); }
+ @Override public CompletableFuture toCompletableFuture() {
+ Object r;
+ if ((r = result) != null)
+ return new CompletableFuture(encodeRelay(r));
+ else {
+ CompletableFuture d = new CompletableFuture<>();
+ unipush(new UniRelay(d, this));
+ return d;
+ }
+ }
}
// VarHandle mechanics
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
index e8f7ac614df..98524dedc23 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
@@ -1191,7 +1191,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* Default idle timeout value (in milliseconds) for the thread
* triggering quiescence to park waiting for new work
*/
- private static final long DEFAULT_KEEPALIVE = 60000L;
+ private static final long DEFAULT_KEEPALIVE = 60_000L;
/**
* Undershoot tolerance for idle timeouts
@@ -2303,7 +2303,6 @@ public class ForkJoinPool extends AbstractExecutorService {
throw new NullPointerException();
long ms = Math.max(unit.toMillis(keepAliveTime), TIMEOUT_SLOP);
- String prefix = "ForkJoinPool-" + nextPoolId() + "-worker-";
int corep = Math.min(Math.max(corePoolSize, parallelism), MAX_CAP);
long c = ((((long)(-corep) << TC_SHIFT) & TC_MASK) |
(((long)(-parallelism) << RC_SHIFT) & RC_MASK));
@@ -2315,8 +2314,8 @@ public class ForkJoinPool extends AbstractExecutorService {
n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;
n = (n + 1) << 1; // power of two, including space for submission queues
+ this.workerNamePrefix = "ForkJoinPool-" + nextPoolId() + "-worker-";
this.workQueues = new WorkQueue[n];
- this.workerNamePrefix = prefix;
this.factory = factory;
this.ueh = handler;
this.saturate = saturate;
@@ -2327,11 +2326,19 @@ public class ForkJoinPool extends AbstractExecutorService {
checkPermission();
}
+ private Object newInstanceFromSystemProperty(String property)
+ throws ReflectiveOperationException {
+ String className = System.getProperty(property);
+ return (className == null)
+ ? null
+ : ClassLoader.getSystemClassLoader().loadClass(className)
+ .getConstructor().newInstance();
+ }
+
/**
* Constructor for common pool using parameters possibly
* overridden by system properties
*/
- @SuppressWarnings("deprecation") // Class.newInstance
private ForkJoinPool(byte forCommonPoolOnly) {
int parallelism = -1;
ForkJoinWorkerThreadFactory fac = null;
@@ -2339,18 +2346,12 @@ public class ForkJoinPool extends AbstractExecutorService {
try { // ignore exceptions in accessing/parsing properties
String pp = System.getProperty
("java.util.concurrent.ForkJoinPool.common.parallelism");
- String fp = System.getProperty
- ("java.util.concurrent.ForkJoinPool.common.threadFactory");
- String hp = System.getProperty
- ("java.util.concurrent.ForkJoinPool.common.exceptionHandler");
if (pp != null)
parallelism = Integer.parseInt(pp);
- if (fp != null)
- fac = ((ForkJoinWorkerThreadFactory)ClassLoader.
- getSystemClassLoader().loadClass(fp).newInstance());
- if (hp != null)
- handler = ((UncaughtExceptionHandler)ClassLoader.
- getSystemClassLoader().loadClass(hp).newInstance());
+ fac = (ForkJoinWorkerThreadFactory) newInstanceFromSystemProperty(
+ "java.util.concurrent.ForkJoinPool.common.threadFactory");
+ handler = (UncaughtExceptionHandler) newInstanceFromSystemProperty(
+ "java.util.concurrent.ForkJoinPool.common.exceptionHandler");
} catch (Exception ignore) {
}
@@ -2373,8 +2374,8 @@ public class ForkJoinPool extends AbstractExecutorService {
n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;
n = (n + 1) << 1;
- this.workQueues = new WorkQueue[n];
this.workerNamePrefix = "ForkJoinPool.commonPool-worker-";
+ this.workQueues = new WorkQueue[n];
this.factory = fac;
this.ueh = handler;
this.saturate = null;
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
index f3e3531dbd9..0d0346f02d6 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
@@ -35,6 +35,9 @@
package java.util.concurrent.atomic;
+import static java.lang.Double.doubleToRawLongBits;
+import static java.lang.Double.longBitsToDouble;
+
import java.io.Serializable;
import java.util.function.DoubleBinaryOperator;
@@ -91,7 +94,7 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
public DoubleAccumulator(DoubleBinaryOperator accumulatorFunction,
double identity) {
this.function = accumulatorFunction;
- base = this.identity = Double.doubleToRawLongBits(identity);
+ base = this.identity = doubleToRawLongBits(identity);
}
/**
@@ -101,18 +104,19 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
*/
public void accumulate(double x) {
Cell[] as; long b, v, r; int m; Cell a;
- if ((as = cells) != null ||
- (r = Double.doubleToRawLongBits
- (function.applyAsDouble
- (Double.longBitsToDouble(b = base), x))) != b && !casBase(b, r)) {
+ if ((as = cells) != null
+ || ((r = doubleToRawLongBits
+ (function.applyAsDouble(longBitsToDouble(b = base), x))) != b
+ && !casBase(b, r))) {
boolean uncontended = true;
- if (as == null || (m = as.length - 1) < 0 ||
- (a = as[getProbe() & m]) == null ||
- !(uncontended =
- (r = Double.doubleToRawLongBits
- (function.applyAsDouble
- (Double.longBitsToDouble(v = a.value), x))) == v ||
- a.cas(v, r)))
+ if (as == null
+ || (m = as.length - 1) < 0
+ || (a = as[getProbe() & m]) == null
+ || !(uncontended =
+ ((r = doubleToRawLongBits
+ (function.applyAsDouble
+ (longBitsToDouble(v = a.value), x))) == v)
+ || a.cas(v, r)))
doubleAccumulate(x, function, uncontended);
}
}
@@ -128,12 +132,12 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
*/
public double get() {
Cell[] as = cells;
- double result = Double.longBitsToDouble(base);
+ double result = longBitsToDouble(base);
if (as != null) {
for (Cell a : as)
if (a != null)
result = function.applyAsDouble
- (result, Double.longBitsToDouble(a.value));
+ (result, longBitsToDouble(a.value));
}
return result;
}
@@ -168,12 +172,12 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
*/
public double getThenReset() {
Cell[] as = cells;
- double result = Double.longBitsToDouble(base);
+ double result = longBitsToDouble(base);
base = identity;
if (as != null) {
for (Cell a : as) {
if (a != null) {
- double v = Double.longBitsToDouble(a.value);
+ double v = longBitsToDouble(a.value);
a.reset(identity);
result = function.applyAsDouble(result, v);
}
@@ -267,9 +271,9 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
* held by this proxy
*/
private Object readResolve() {
- double d = Double.longBitsToDouble(identity);
+ double d = longBitsToDouble(identity);
DoubleAccumulator a = new DoubleAccumulator(function, d);
- a.base = Double.doubleToRawLongBits(value);
+ a.base = doubleToRawLongBits(value);
return a;
}
}
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java
index 939a4a2eed9..8c6e332ad79 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java
@@ -103,14 +103,16 @@ public class LongAccumulator extends Striped64 implements Serializable {
*/
public void accumulate(long x) {
Cell[] as; long b, v, r; int m; Cell a;
- if ((as = cells) != null ||
- (r = function.applyAsLong(b = base, x)) != b && !casBase(b, r)) {
+ if ((as = cells) != null
+ || ((r = function.applyAsLong(b = base, x)) != b
+ && !casBase(b, r))) {
boolean uncontended = true;
- if (as == null || (m = as.length - 1) < 0 ||
- (a = as[getProbe() & m]) == null ||
- !(uncontended =
- (r = function.applyAsLong(v = a.value, x)) == v ||
- a.cas(v, r)))
+ if (as == null
+ || (m = as.length - 1) < 0
+ || (a = as[getProbe() & m]) == null
+ || !(uncontended =
+ (r = function.applyAsLong(v = a.value, x)) == v
+ || a.cas(v, r)))
longAccumulate(x, function, uncontended);
}
}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java
index 07038b9ef5e..10506b7029c 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java
@@ -186,7 +186,9 @@ public class BasicImageReader implements AutoCloseable {
if (result.getMajorVersion() != ImageHeader.MAJOR_VERSION ||
result.getMinorVersion() != ImageHeader.MINOR_VERSION) {
- throw new IOException("The image file \"" + name + "\" is not the correct version");
+ throw new IOException("The image file \"" + name + "\" is not " +
+ "the correct version. Major: " + result.getMajorVersion() +
+ ". Minor: " + result.getMinorVersion());
}
return result;
@@ -318,11 +320,11 @@ public class BasicImageReader implements AutoCloseable {
private ByteBuffer readBuffer(long offset, long size) {
if (offset < 0 || Integer.MAX_VALUE <= offset) {
- throw new IndexOutOfBoundsException("offset");
+ throw new IndexOutOfBoundsException("Bad offset: " + offset);
}
if (size < 0 || Integer.MAX_VALUE <= size) {
- throw new IndexOutOfBoundsException("size");
+ throw new IndexOutOfBoundsException("Bad size: " + size);
}
if (MAP_ALL) {
@@ -382,11 +384,13 @@ public class BasicImageReader implements AutoCloseable {
long uncompressedSize = loc.getUncompressedSize();
if (compressedSize < 0 || Integer.MAX_VALUE < compressedSize) {
- throw new IndexOutOfBoundsException("Compressed size");
+ throw new IndexOutOfBoundsException(
+ "Bad compressed size: " + compressedSize);
}
if (uncompressedSize < 0 || Integer.MAX_VALUE < uncompressedSize) {
- throw new IndexOutOfBoundsException("Uncompressed size");
+ throw new IndexOutOfBoundsException(
+ "Bad uncompressed size: " + uncompressedSize);
}
if (compressedSize == 0) {
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java
index c4ff85bbfb8..f63665119e2 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java
@@ -79,7 +79,8 @@ public final class ImageHeader {
Objects.requireNonNull(buffer);
if (buffer.capacity() != HEADER_SLOTS) {
- throw new InternalError("jimage header not the correct size");
+ throw new InternalError(
+ "jimage header not the correct size: " + buffer.capacity());
}
int magic = buffer.get(0);
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java
index 16787dad3af..ad0ae42fc3d 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java
@@ -81,7 +81,8 @@ public class ImageLocation {
}
if (kind < ATTRIBUTE_END || ATTRIBUTE_COUNT <= kind) {
- throw new InternalError("Invalid jimage attribute kind");
+ throw new InternalError(
+ "Invalid jimage attribute kind: " + kind);
}
int length = attributeLength(data);
@@ -91,7 +92,7 @@ public class ImageLocation {
value <<= 8;
if (!bytes.hasRemaining()) {
- throw new InternalError("\"Missing jimage attribute datad");
+ throw new InternalError("Missing jimage attribute data");
}
value |= bytes.get() & 0xFF;
@@ -134,7 +135,8 @@ public class ImageLocation {
long getAttribute(int kind) {
if (kind < ATTRIBUTE_END || ATTRIBUTE_COUNT <= kind) {
- throw new InternalError("Invalid jimage attribute kind");
+ throw new InternalError(
+ "Invalid jimage attribute kind: " + kind);
}
return attributes[kind];
@@ -142,7 +144,8 @@ public class ImageLocation {
String getAttributeString(int kind) {
if (kind < ATTRIBUTE_END || ATTRIBUTE_COUNT <= kind) {
- throw new InternalError("Invalid jimage attribute kind");
+ throw new InternalError(
+ "Invalid jimage attribute kind: " + kind);
}
return getStrings().get((int)attributes[kind]);
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java
index 9802afcc93a..774e0e6e62a 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java
@@ -82,7 +82,7 @@ public class ImageStream {
public void ensure(int needs) {
if (needs < 0) {
- throw new IndexOutOfBoundsException("needs");
+ throw new IndexOutOfBoundsException("Bad value: " + needs);
}
if (needs > buffer.remaining()) {
@@ -106,7 +106,7 @@ public class ImageStream {
public void skip(int n) {
if (n < 0) {
- throw new IndexOutOfBoundsException("n");
+ throw new IndexOutOfBoundsException("skip value = " + n);
}
buffer.position(buffer.position() + n);
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java
index 382e6b1696b..e4a11cbdc14 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java
@@ -151,7 +151,7 @@ public class ImageStringsReader implements ImageStrings {
try {
charsFromMUTF8(chars, bytes, offset, count);
} catch (UTFDataFormatException ex) {
- throw new InternalError("Attempt to convert non modified UTF-8 byte sequence");
+ throw new InternalError("Attempt to convert non modified UTF-8 byte sequence", ex);
}
return new String(chars);
@@ -199,7 +199,8 @@ public class ImageStringsReader implements ImageStrings {
ch = buffer.get();
if ((ch & 0xC0) != 0x80) {
- throw new InternalError("Bad continuation in modified UTF-8 byte sequence");
+ throw new InternalError("Bad continuation in " +
+ "modified UTF-8 byte sequence: " + ch);
}
uch = ((uch & ~mask) << 6) | (ch & 0x3F);
@@ -208,7 +209,8 @@ public class ImageStringsReader implements ImageStrings {
}
if ((uch & 0xFFFF) != uch) {
- throw new InternalError("UTF-32 char in modified UTF-8 byte sequence");
+ throw new InternalError("UTF-32 char in modified UTF-8 " +
+ "byte sequence: " + uch);
}
chars[j++] = (char)uch;
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java
index cb6c85d11e3..49285b31dfb 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java
@@ -183,7 +183,7 @@ class JrtFileSystem extends FileSystem {
public PathMatcher getPathMatcher(String syntaxAndInput) {
int pos = syntaxAndInput.indexOf(':');
if (pos <= 0 || pos == syntaxAndInput.length()) {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("pos is " + pos);
}
String syntax = syntaxAndInput.substring(0, pos);
String input = syntaxAndInput.substring(pos + 1);
@@ -285,7 +285,8 @@ class JrtFileSystem extends FileSystem {
for (OpenOption option : options) {
Objects.requireNonNull(option);
if (!(option instanceof StandardOpenOption)) {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException(
+ "option class: " + option.getClass());
}
}
if (options.contains(StandardOpenOption.WRITE) ||
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java
index cf3bbd8d2d9..f23887cabad 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java
@@ -122,7 +122,8 @@ final class JrtPath implements Path {
public final JrtPath getName(int index) {
initOffsets();
if (index < 0 || index >= offsets.length) {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("index: " +
+ index + ", offsets length: " + offsets.length);
}
int begin = offsets[index];
int end;
@@ -139,7 +140,9 @@ final class JrtPath implements Path {
initOffsets();
if (beginIndex < 0 || endIndex > offsets.length ||
beginIndex >= endIndex) {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException(
+ "beginIndex: " + beginIndex + ", endIndex: " + endIndex +
+ ", offsets length: " + offsets.length);
}
// starting/ending offsets
int begin = offsets[beginIndex];
@@ -211,7 +214,8 @@ final class JrtPath implements Path {
return o;
}
if (jrtfs != o.jrtfs || isAbsolute() != o.isAbsolute()) {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException(
+ "Incorrect filesystem or path: " + other);
}
final String tp = this.path;
final String op = o.path;
@@ -366,7 +370,8 @@ final class JrtPath implements Path {
private JrtPath checkPath(Path path) {
Objects.requireNonNull(path);
if (!(path instanceof JrtPath))
- throw new ProviderMismatchException();
+ throw new ProviderMismatchException("path class: " +
+ path.getClass());
return (JrtPath) path;
}
@@ -459,7 +464,7 @@ final class JrtPath implements Path {
}
if (c == '\u0000') {
throw new InvalidPathException(path,
- "Path: nul character not allowed");
+ "Path: NUL character not allowed");
}
to.append(c);
prevC = c;
diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
index a5f3126c16f..f4de0ea0c47 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
@@ -1603,11 +1603,50 @@ public final class Unsafe {
return weakCompareAndSwapShort(o, offset, c2s(expected), c2s(x));
}
+ /**
+ * The JVM converts integral values to boolean values using two
+ * different conventions, byte testing against zero and truncation
+ * to least-significant bit.
+ *
+ * The JNI documents specify that, at least for returning
+ * values from native methods, a Java boolean value is converted
+ * to the value-set 0..1 by first truncating to a byte (0..255 or
+ * maybe -128..127) and then testing against zero. Thus, Java
+ * booleans in non-Java data structures are by convention
+ * represented as 8-bit containers containing either zero (for
+ * false) or any non-zero value (for true).
+ *
+ *
Java booleans in the heap are also stored in bytes, but are
+ * strongly normalized to the value-set 0..1 (i.e., they are
+ * truncated to the least-significant bit).
+ *
+ *
The main reason for having different conventions for
+ * conversion is performance: Truncation to the least-significant
+ * bit can be usually implemented with fewer (machine)
+ * instructions than byte testing against zero.
+ *
+ *
A number of Unsafe methods load boolean values from the heap
+ * as bytes. Unsafe converts those values according to the JNI
+ * rules (i.e, using the "testing against zero" convention). The
+ * method {@code byte2bool} implements that conversion.
+ *
+ * @param b the byte to be converted to boolean
+ * @return the result of the conversion
+ */
@ForceInline
private boolean byte2bool(byte b) {
- return b > 0;
+ return b != 0;
}
+ /**
+ * Convert a boolean value to a byte. The return value is strongly
+ * normalized to the value-set 0..1 (i.e., the value is truncated
+ * to the least-significant bit). See {@link #byte2bool(byte)} for
+ * more details on conversion conventions.
+ *
+ * @param b the boolean to be converted to byte (and then normalized)
+ * @return the result of the conversion
+ */
@ForceInline
private byte bool2byte(boolean b) {
return b ? (byte)1 : (byte)0;
diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java
index 9fe63d56e5e..695795e4338 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java
@@ -50,7 +50,7 @@ public class VM {
public static void initLevel(int value) {
synchronized (lock) {
if (value <= initLevel || value > SYSTEM_BOOTED)
- throw new InternalError();
+ throw new InternalError("Bad level: " + value);
initLevel = value;
lock.notifyAll();
}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java
index b9b93b275ef..ca40bf2706e 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java
@@ -153,27 +153,24 @@ public final class ModuleBootstrap {
boolean addAllDefaultModules = false;
boolean addAllSystemModules = false;
boolean addAllApplicationModules = false;
- String propValue = getAndRemoveProperty("jdk.module.addmods");
- if (propValue != null) {
- for (String mod: propValue.split(",")) {
- switch (mod) {
- case ALL_DEFAULT:
- addAllDefaultModules = true;
- break;
- case ALL_SYSTEM:
- addAllSystemModules = true;
- break;
- case ALL_MODULE_PATH:
- addAllApplicationModules = true;
- break;
- default :
- roots.add(mod);
- }
+ for (String mod: getExtraAddModules()) {
+ switch (mod) {
+ case ALL_DEFAULT:
+ addAllDefaultModules = true;
+ break;
+ case ALL_SYSTEM:
+ addAllSystemModules = true;
+ break;
+ case ALL_MODULE_PATH:
+ addAllApplicationModules = true;
+ break;
+ default :
+ roots.add(mod);
}
}
// --limit-modules
- propValue = getAndRemoveProperty("jdk.module.limitmods");
+ String propValue = getAndRemoveProperty("jdk.module.limitmods");
if (propValue != null) {
Set mods = new HashSet<>();
for (String mod: propValue.split(",")) {
@@ -392,6 +389,32 @@ public final class ModuleBootstrap {
}
}
+ /**
+ * Returns the set of module names specified via --add-modules options
+ * on the command line
+ */
+ private static Set getExtraAddModules() {
+ String prefix = "jdk.module.addmods.";
+ int index = 0;
+
+ // the system property is removed after decoding
+ String value = getAndRemoveProperty(prefix + index);
+ if (value == null) {
+ return Collections.emptySet();
+ }
+
+ Set modules = new HashSet<>();
+ while (value != null) {
+ for (String s : value.split(",")) {
+ if (s.length() > 0) modules.add(s);
+ }
+
+ index++;
+ value = getAndRemoveProperty(prefix + index);
+ }
+
+ return modules;
+ }
/**
* Process the --add-reads options to add any additional read edges that
@@ -514,7 +537,7 @@ public final class ModuleBootstrap {
// value is (,)*
if (map.containsKey(key))
- fail(key + " specified more than once");
+ fail(key + " specified more than once");
Set values = new HashSet<>();
map.put(key, values);
diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java
index f49111be646..11d53463dc8 100644
--- a/jdk/src/java.base/share/classes/module-info.java
+++ b/jdk/src/java.base/share/classes/module-info.java
@@ -166,6 +166,7 @@ module java.base {
jdk.charsets,
jdk.compiler,
jdk.jartool,
+ jdk.jdeps,
jdk.jlink,
jdk.net,
jdk.scripting.nashorn,
@@ -189,7 +190,8 @@ module java.base {
jdk.unsupported,
jdk.vm.ci;
exports jdk.internal.util.jar to
- jdk.jartool;
+ jdk.jartool,
+ jdk.jdeps;
exports jdk.internal.vm to
java.management,
jdk.jvmstat;
diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java
index f063e13ac13..7f63ec88264 100644
--- a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java
@@ -328,8 +328,6 @@ class DatagramChannelImpl
public SocketAddress receive(ByteBuffer dst) throws IOException {
if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
- if (dst == null)
- throw new NullPointerException();
synchronized (readLock) {
ensureOpen();
// Socket was not bound before attempting receive
@@ -716,8 +714,6 @@ class DatagramChannelImpl
@Override
public DatagramChannel connect(SocketAddress sa) throws IOException {
- int localPort = 0;
-
synchronized(readLock) {
synchronized(writeLock) {
synchronized (stateLock) {
diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java
index 856e0cf2fb6..8e21e522079 100644
--- a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java
@@ -616,8 +616,6 @@ class SocketChannelImpl
}
public boolean connect(SocketAddress sa) throws IOException {
- int localPort = 0;
-
synchronized (readLock) {
synchronized (writeLock) {
ensureOpenAndUnconnected();
diff --git a/jdk/src/java.base/share/classes/sun/security/provider/SeedGenerator.java b/jdk/src/java.base/share/classes/sun/security/provider/SeedGenerator.java
index e72ae9f406c..ac3a9f86a1a 100644
--- a/jdk/src/java.base/share/classes/sun/security/provider/SeedGenerator.java
+++ b/jdk/src/java.base/share/classes/sun/security/provider/SeedGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -344,7 +344,8 @@ abstract class SeedGenerator {
try {
BogusThread bt = new BogusThread();
Thread t = new Thread
- (seedGroup, bt, "SeedGenerator Thread", 0, false);
+ (seedGroup, bt, "SeedGenerator Thread", 0,
+ false);
t.start();
} catch (Exception e) {
throw new InternalError("internal error: " +
@@ -357,7 +358,8 @@ abstract class SeedGenerator {
long startTime = System.nanoTime();
while (System.nanoTime() - startTime < 250000000) {
synchronized(this){};
- latch++;
+ // Mask the sign bit and keep latch non-negative
+ latch = (latch + 1) & 0x1FFFFFFF;
}
// Translate the value using the permutation, and xor
@@ -431,7 +433,7 @@ abstract class SeedGenerator {
// data and using it to mix the trivial permutation.
// It should be evenly distributed. The specific values
// are not crucial to the security of this class.
- private static byte[] rndTab = {
+ private static final byte[] rndTab = {
56, 30, -107, -6, -86, 25, -83, 75, -12, -64,
5, -128, 78, 21, 16, 32, 70, -81, 37, -51,
-43, -46, -108, 87, 29, 17, -55, 22, -11, -111,
diff --git a/jdk/src/java.base/share/classes/sun/security/rsa/RSASignature.java b/jdk/src/java.base/share/classes/sun/security/rsa/RSASignature.java
index 7c707bbb15e..43e605a1457 100644
--- a/jdk/src/java.base/share/classes/sun/security/rsa/RSASignature.java
+++ b/jdk/src/java.base/share/classes/sun/security/rsa/RSASignature.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -182,14 +182,15 @@ public abstract class RSASignature extends SignatureSpi {
}
// verify the data and return the result. See JCA doc
+ // should be reset to the state after engineInitVerify call.
protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
- if (sigBytes.length != RSACore.getByteLength(publicKey)) {
- throw new SignatureException("Signature length not correct: got " +
+ try {
+ if (sigBytes.length != RSACore.getByteLength(publicKey)) {
+ throw new SignatureException("Signature length not correct: got " +
sigBytes.length + " but was expecting " +
RSACore.getByteLength(publicKey));
- }
- byte[] digest = getDigestValue();
- try {
+ }
+ byte[] digest = getDigestValue();
byte[] decrypted = RSACore.rsa(sigBytes, publicKey);
byte[] unpadded = padding.unpad(decrypted);
byte[] decodedDigest = decodeSignature(digestOID, unpadded);
@@ -202,6 +203,8 @@ public abstract class RSASignature extends SignatureSpi {
return false;
} catch (IOException e) {
throw new SignatureException("Signature encoding error", e);
+ } finally {
+ resetDigest();
}
}
diff --git a/jdk/src/java.base/share/native/include/jvm.h b/jdk/src/java.base/share/native/include/jvm.h
index bf60a857beb..1d6576a6381 100644
--- a/jdk/src/java.base/share/native/include/jvm.h
+++ b/jdk/src/java.base/share/native/include/jvm.h
@@ -179,6 +179,7 @@ JVM_GetStackTraceElements(JNIEnv *env, jobject throwable, jobjectArray elements)
*/
enum {
JVM_STACKWALK_FILL_CLASS_REFS_ONLY = 0x2,
+ JVM_STACKWALK_GET_CALLER_CLASS = 0x04,
JVM_STACKWALK_SHOW_HIDDEN_FRAMES = 0x20,
JVM_STACKWALK_FILL_LIVE_STACK_FRAMES = 0x100
};
diff --git a/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c b/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c
index 27230858253..533584fdb7a 100644
--- a/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c
+++ b/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c
@@ -152,8 +152,8 @@ defaultPath(void)
#ifdef __solaris__
/* These really are the Solaris defaults! */
return (geteuid() == 0 || getuid() == 0) ?
- "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
- "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:";
+ "/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
+ "/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:";
#else
return ":/bin:/usr/bin"; /* glibc */
#endif
diff --git a/jdk/src/java.base/unix/native/libjli/java_md.h b/jdk/src/java.base/unix/native/libjli/java_md.h
index ab99dbbdf66..8e95aced972 100644
--- a/jdk/src/java.base/unix/native/libjli/java_md.h
+++ b/jdk/src/java.base/unix/native/libjli/java_md.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,12 +35,12 @@
#include "manifest_info.h"
#include "jli_util.h"
-#define PATH_SEPARATOR ':'
-#define FILESEP "/"
-#define FILE_SEPARATOR '/'
+#define PATH_SEPARATOR ':'
+#define FILESEP "/"
+#define FILE_SEPARATOR '/'
#define IS_FILE_SEPARATOR(c) ((c) == '/')
#ifndef MAXNAMELEN
-#define MAXNAMELEN PATH_MAX
+#define MAXNAMELEN PATH_MAX
#endif
#ifdef _LP64
@@ -59,10 +59,13 @@ static jboolean GetJVMPath(const char *jrepath, const char *jvmtype,
static jboolean GetJREPath(char *path, jint pathsize, const char * arch,
jboolean speculative);
+#if defined(_AIX)
+#include "java_md_aix.h"
+#endif
+
#ifdef MACOSX
#include "java_md_macosx.h"
#else /* !MACOSX */
#include "java_md_solinux.h"
#endif /* MACOSX */
-
#endif /* JAVA_MD_H */
diff --git a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c
index f141ad234c4..84737d20c03 100644
--- a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c
+++ b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c
@@ -1302,7 +1302,7 @@ static void mcast_set_loop_v6(JNIEnv *env, jobject this, int fd, jobject value)
* Sets the multicast loopback mode.
*/
static void setMulticastLoopbackMode(JNIEnv *env, jobject this, int fd,
- jint opt, jobject value) {
+ jint opt, jobject value) {
#ifdef AF_INET6
#ifdef __linux__
mcast_set_loop_v4(env, this, fd, value);
@@ -1330,10 +1330,9 @@ static void setMulticastLoopbackMode(JNIEnv *env, jobject this, int fd,
* Signature: (ILjava/lang/Object;)V
*/
JNIEXPORT void JNICALL
-Java_java_net_PlainDatagramSocketImpl_socketSetOption0(JNIEnv *env,
- jobject this,
- jint opt,
- jobject value) {
+Java_java_net_PlainDatagramSocketImpl_socketSetOption0
+ (JNIEnv *env, jobject this, jint opt, jobject value)
+{
int fd;
int level, optname, optlen;
int optval;
@@ -1380,7 +1379,7 @@ Java_java_net_PlainDatagramSocketImpl_socketSetOption0(JNIEnv *env,
* level and option name.
*/
if (NET_MapSocketOption(opt, &level, &optname)) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
+ JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
return;
}
@@ -1699,8 +1698,9 @@ jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, jint opt) {
* Signature: (I)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL
-Java_java_net_PlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobject this,
- jint opt) {
+Java_java_net_PlainDatagramSocketImpl_socketGetOption
+ (JNIEnv *env, jobject this, jint opt)
+{
int fd;
int level, optname, optlen;
union {
@@ -1751,7 +1751,7 @@ Java_java_net_PlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobject this,
* level and option name.
*/
if (NET_MapSocketOption(opt, &level, &optname)) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
+ JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
return NULL;
}
diff --git a/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c b/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c
index ba8e483c101..c7766751507 100644
--- a/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c
+++ b/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c
@@ -855,9 +855,9 @@ Java_java_net_PlainSocketImpl_socketShutdown(JNIEnv *env, jobject this,
* Signature: (IZLjava/lang/Object;)V
*/
JNIEXPORT void JNICALL
-Java_java_net_PlainSocketImpl_socketSetOption0(JNIEnv *env, jobject this,
- jint cmd, jboolean on,
- jobject value) {
+Java_java_net_PlainSocketImpl_socketSetOption0
+ (JNIEnv *env, jobject this, jint cmd, jboolean on, jobject value)
+{
int fd;
int level, optname, optlen;
union {
@@ -887,7 +887,7 @@ Java_java_net_PlainSocketImpl_socketSetOption0(JNIEnv *env, jobject this,
* level and option name.
*/
if (NET_MapSocketOption(cmd, &level, &optname)) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
+ JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
return;
}
@@ -951,9 +951,9 @@ Java_java_net_PlainSocketImpl_socketSetOption0(JNIEnv *env, jobject this,
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
-Java_java_net_PlainSocketImpl_socketGetOption(JNIEnv *env, jobject this,
- jint cmd, jobject iaContainerObj) {
-
+Java_java_net_PlainSocketImpl_socketGetOption
+ (JNIEnv *env, jobject this, jint cmd, jobject iaContainerObj)
+{
int fd;
int level, optname, optlen;
union {
@@ -1004,7 +1004,7 @@ Java_java_net_PlainSocketImpl_socketGetOption(JNIEnv *env, jobject this,
* level and option name.
*/
if (NET_MapSocketOption(cmd, &level, &optname)) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
+ JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
return -1;
}
diff --git a/jdk/src/java.base/unix/native/libnet/SocketInputStream.c b/jdk/src/java.base/unix/native/libnet/SocketInputStream.c
index 380c03bfeaa..a27902b1f83 100644
--- a/jdk/src/java.base/unix/native/libnet/SocketInputStream.c
+++ b/jdk/src/java.base/unix/native/libnet/SocketInputStream.c
@@ -58,15 +58,15 @@ static int NET_ReadWithTimeout(JNIEnv *env, int fd, char *bufP, int len, long ti
result = NET_TimeoutWithCurrentTime(fd, timeout, prevtime);
if (result <= 0) {
if (result == 0) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", "Read timed out");
+ JNU_ThrowByName(env, "java/net/SocketTimeoutException", "Read timed out");
} else if (result == -1) {
if (errno == EBADF) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+ JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
} else if (errno == ENOMEM) {
JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
} else {
JNU_ThrowByNameWithMessageAndLastError
- (env, JNU_JAVANETPKG "SocketException", "select/poll failed");
+ (env, "java/net/SocketException", "select/poll failed");
}
}
return -1;
@@ -100,19 +100,14 @@ Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
jint fd, nread;
if (IS_NULL(fdObj)) {
- /* shouldn't this be a NullPointerException? -br */
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ JNU_ThrowByName(env, "java/net/SocketException",
"Socket closed");
return -1;
- } else {
- fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
- /* Bug 4086704 - If the Socket associated with this file descriptor
- * was closed (sysCloseFD), then the file descriptor is set to -1.
- */
- if (fd == -1) {
- JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
- return -1;
- }
+ }
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ if (fd == -1) {
+ JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
+ return -1;
}
/*
@@ -154,17 +149,17 @@ Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
break;
case EBADF:
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ JNU_ThrowByName(env, "java/net/SocketException",
"Socket closed");
break;
case EINTR:
- JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
+ JNU_ThrowByName(env, "java/io/InterruptedIOException",
"Operation interrupted");
break;
default:
JNU_ThrowByNameWithMessageAndLastError
- (env, JNU_JAVANETPKG "SocketException", "Read failed");
+ (env, "java/net/SocketException", "Read failed");
}
}
} else {
diff --git a/jdk/src/java.base/unix/native/libnio/ch/NativeThread.c b/jdk/src/java.base/unix/native/libnio/ch/NativeThread.c
index fd20eeff79c..0b644158537 100644
--- a/jdk/src/java.base/unix/native/libnio/ch/NativeThread.c
+++ b/jdk/src/java.base/unix/native/libnio/ch/NativeThread.c
@@ -37,6 +37,11 @@
#include
/* Also defined in net/linux_close.c */
#define INTERRUPT_SIGNAL (__SIGRTMAX - 2)
+#elif _AIX
+ #include
+ #include
+ /* Also defined in net/aix_close.c */
+ #define INTERRUPT_SIGNAL (SIGRTMAX - 1)
#elif __solaris__
#include
#include
@@ -59,7 +64,7 @@ JNIEXPORT void JNICALL
Java_sun_nio_ch_NativeThread_init(JNIEnv *env, jclass cl)
{
/* Install the null handler for INTERRUPT_SIGNAL. This might overwrite the
- * handler previously installed by java/net/linux_close.c, but that's okay
+ * handler previously installed by _close.c, but that's okay
* since neither handler actually does anything. We install our own
* handler here simply out of paranoia; ultimately the two mechanisms
* should somehow be unified, perhaps within the VM.
diff --git a/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c b/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c
index c1f1ae839fc..3ea2333fa08 100644
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -475,13 +475,14 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSend
* Method: socketSetIntOption
* Signature: (III)V
*/
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSetIntOption
- (JNIEnv *env, jclass clazz, jint fd , jint cmd, jint value) {
+JNIEXPORT void JNICALL
+Java_java_net_DualStackPlainDatagramSocketImpl_socketSetIntOption
+ (JNIEnv *env, jclass clazz, jint fd, jint cmd, jint value)
+{
int level = 0, opt = 0;
if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
- JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "Invalid option");
+ JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
return;
}
@@ -495,14 +496,15 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSetI
* Method: socketGetIntOption
* Signature: (II)I
*/
-JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketGetIntOption
- (JNIEnv *env, jclass clazz, jint fd, jint cmd) {
- int level = 0, opt = 0, result=0;
+JNIEXPORT jint JNICALL
+Java_java_net_DualStackPlainDatagramSocketImpl_socketGetIntOption
+ (JNIEnv *env, jclass clazz, jint fd, jint cmd)
+{
+ int level = 0, opt = 0, result = 0;
int result_len = sizeof(result);
if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
- JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "Invalid option");
+ JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
return -1;
}
@@ -519,8 +521,10 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketGetI
* Method: dataAvailable
* Signature: ()I
*/
-JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_dataAvailable
-(JNIEnv *env, jobject this) {
+JNIEXPORT jint JNICALL
+Java_java_net_DualStackPlainDatagramSocketImpl_dataAvailable
+ (JNIEnv *env, jobject this)
+{
SOCKET fd;
int rv = -1;
jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
diff --git a/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c b/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c
index eccf785b23f..0fa6d79be6a 100644
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -369,18 +369,17 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_shutdown0
* Method: setIntOption
* Signature: (III)V
*/
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_setIntOption
- (JNIEnv *env, jclass clazz, jint fd, jint cmd, jint value) {
-
+JNIEXPORT void JNICALL
+Java_java_net_DualStackPlainSocketImpl_setIntOption
+ (JNIEnv *env, jclass clazz, jint fd, jint cmd, jint value)
+{
int level = 0, opt = 0;
struct linger linger = {0, 0};
char *parg;
int arglen;
if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
- JNU_ThrowByNameWithLastError(env,
- JNU_JAVANETPKG "SocketException",
- "Invalid option");
+ JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
return;
}
@@ -410,8 +409,8 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_setIntOption
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_getIntOption
- (JNIEnv *env, jclass clazz, jint fd, jint cmd) {
-
+ (JNIEnv *env, jclass clazz, jint fd, jint cmd)
+{
int level = 0, opt = 0;
int result=0;
struct linger linger = {0, 0};
@@ -419,9 +418,7 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_getIntOption
int arglen;
if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
- JNU_ThrowByNameWithLastError(env,
- JNU_JAVANETPKG "SocketException",
- "Unsupported socket option");
+ JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
return -1;
}
diff --git a/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c b/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c
index 30b2a93ffcc..3a9e650a5f8 100644
--- a/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c
+++ b/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
#include "java_net_InetAddress.h"
#include "java_net_Inet4AddressImpl.h"
@@ -442,7 +443,15 @@ ping4(JNIEnv *env,
DWORD ReplySize = 0;
jboolean ret = JNI_FALSE;
- ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData);
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/aa366051%28v=vs.85%29.aspx
+ ReplySize = sizeof(ICMP_ECHO_REPLY) // The buffer should be large enough
+ // to hold at least one ICMP_ECHO_REPLY
+ // structure
+ + sizeof(SendData) // plus RequestSize bytes of data.
+ + 8; // This buffer should also be large enough
+ // to also hold 8 more bytes of data
+ // (the size of an ICMP error message)
+
ReplyBuffer = (VOID*) malloc(ReplySize);
if (ReplyBuffer == NULL) {
IcmpCloseHandle(hIcmpFile);
@@ -478,10 +487,47 @@ ping4(JNIEnv *env,
(timeout < 1000) ? 1000 : timeout); // DWORD Timeout
}
- if (dwRetVal != 0) {
+ if (dwRetVal == 0) { // if the call failed
+ TCHAR *buf;
+ DWORD err = WSAGetLastError();
+ switch (err) {
+ case ERROR_NO_NETWORK:
+ case ERROR_NETWORK_UNREACHABLE:
+ case ERROR_HOST_UNREACHABLE:
+ case ERROR_PROTOCOL_UNREACHABLE:
+ case ERROR_PORT_UNREACHABLE:
+ case ERROR_REQUEST_ABORTED:
+ case ERROR_INCORRECT_ADDRESS:
+ case ERROR_HOST_DOWN:
+ case ERROR_INVALID_COMPUTERNAME:
+ case ERROR_INVALID_NETNAME:
+ case WSAEHOSTUNREACH: /* Host Unreachable */
+ case WSAENETUNREACH: /* Network Unreachable */
+ case WSAENETDOWN: /* Network is down */
+ case WSAEPFNOSUPPORT: /* Protocol Family unsupported */
+ case IP_REQ_TIMED_OUT:
+ break;
+ default:
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR)&buf, 0, NULL);
+ NET_ThrowNew(env, err, buf);
+ LocalFree(buf);
+ break;
+ }
+ } else {
PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer;
- if ((int)pEchoReply->RoundTripTime <= timeout)
+
+ // This is to take into account the undocumented minimum
+ // timeout mentioned in the IcmpSendEcho call above.
+ // We perform an extra check to make sure that our
+ // roundtrip time was less than our desired timeout
+ // for cases where that timeout is < 1000ms.
+ if (pEchoReply->Status == IP_SUCCESS
+ && (int)pEchoReply->RoundTripTime <= timeout)
+ {
ret = JNI_TRUE;
+ }
}
free(ReplyBuffer);
diff --git a/jdk/src/java.base/windows/native/libnet/SocketInputStream.c b/jdk/src/java.base/windows/native/libnet/SocketInputStream.c
index fe0adfba9ad..3e9da6e7176 100644
--- a/jdk/src/java.base/windows/native/libnet/SocketInputStream.c
+++ b/jdk/src/java.base/windows/native/libnet/SocketInputStream.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -62,18 +62,18 @@ Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
jobject fdObj, jbyteArray data,
jint off, jint len, jint timeout)
{
- char *bufP;
char BUF[MAX_BUFFER_LEN];
- jint fd, newfd;
- jint nread;
+ char *bufP;
+ jint fd, newfd, nread;
if (IS_NULL(fdObj)) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
+ JNU_ThrowByName(env, "java/net/SocketException",
+ "Socket closed");
return -1;
}
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
if (fd == -1) {
- NET_ThrowSocketException(env, "Socket closed");
+ JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
return -1;
}
@@ -103,10 +103,10 @@ Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
if (ret <= 0) {
if (ret == 0) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+ JNU_ThrowByName(env, "java/net/SocketTimeoutException",
"Read timed out");
} else if (ret == -1) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
+ JNU_ThrowByName(env, "java/net/SocketException", "socket closed");
}
if (bufP != BUF) {
free(bufP);
@@ -117,7 +117,7 @@ Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
/*check if the socket has been closed while we were in timeout*/
newfd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
if (newfd == -1) {
- NET_ThrowSocketException(env, "Socket Closed");
+ JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
if (bufP != BUF) {
free(bufP);
}
@@ -134,11 +134,11 @@ Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
// Check if the socket has been closed since we last checked.
// This could be a reason for recv failing.
if ((*env)->GetIntField(env, fdObj, IO_fd_fdID) == -1) {
- NET_ThrowSocketException(env, "Socket closed");
+ JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
} else {
switch (WSAGetLastError()) {
case WSAEINTR:
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ JNU_ThrowByName(env, "java/net/SocketException",
"socket closed");
break;
@@ -153,7 +153,7 @@ Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
break;
case WSAETIMEDOUT :
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+ JNU_ThrowByName(env, "java/net/SocketTimeoutException",
"Read timed out");
break;
diff --git a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c
index b37adf7e1d4..84fd4a59e89 100644
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c
@@ -1795,9 +1795,9 @@ static void setMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1,
* Signature: (ILjava/lang/Object;)V
*/
JNIEXPORT void JNICALL
-Java_java_net_TwoStacksPlainDatagramSocketImpl_socketNativeSetOption(JNIEnv *env,jobject this,
- jint opt,jobject value) {
-
+Java_java_net_TwoStacksPlainDatagramSocketImpl_socketNativeSetOption
+ (JNIEnv *env,jobject this, jint opt,jobject value)
+{
int fd=-1, fd1=-1;
int levelv4 = 0, levelv6 = 0, optnamev4 = 0, optnamev6 = 0, optlen = 0;
union {
@@ -1828,13 +1828,13 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_socketNativeSetOption(JNIEnv *env
*/
if (fd1 != -1) {
if (NET_MapSocketOptionV6(opt, &levelv6, &optnamev6)) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
+ JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
return;
}
}
if (fd != -1) {
if (NET_MapSocketOption(opt, &levelv4, &optnamev4)) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
+ JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
return;
}
}
@@ -2163,9 +2163,9 @@ jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, jint o
* Signature: (I)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL
-Java_java_net_TwoStacksPlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobject this,
- jint opt) {
-
+Java_java_net_TwoStacksPlainDatagramSocketImpl_socketGetOption
+ (JNIEnv *env, jobject this, jint opt)
+{
int fd=-1, fd1=-1;
int level, optname, optlen;
union {
@@ -2197,13 +2197,13 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobj
* level and option name.
*/
if (NET_MapSocketOption(opt, &level, &optname)) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
+ JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
return NULL;
}
if (fd == -1) {
if (NET_MapSocketOptionV6(opt, &level, &optname)) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
+ JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
return NULL;
}
fd = fd1; /* must be IPv6 only */
diff --git a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c
index 3d950d3d4ad..ace7b944bd5 100644
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c
@@ -838,10 +838,9 @@ Java_java_net_TwoStacksPlainSocketImpl_socketClose0(JNIEnv *env, jobject this,
* Signature: (IZLjava/lang/Object;)V
*/
JNIEXPORT void JNICALL
-Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption(JNIEnv *env,
- jobject this,
- jint cmd, jboolean on,
- jobject value) {
+Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption
+ (JNIEnv *env, jobject this, jint cmd, jboolean on, jobject value)
+{
int fd, fd1;
int level = 0, optname = 0, optlen = 0;
union {
@@ -923,11 +922,10 @@ Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption(JNIEnv *env,
/*
* Map the Java level socket option to the platform specific
- * level
+ * level and option name.
*/
if (NET_MapSocketOption(cmd, &level, &optname)) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "Invalid option");
+ JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
return;
}
@@ -1006,15 +1004,16 @@ Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption(JNIEnv *env,
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
-Java_java_net_TwoStacksPlainSocketImpl_socketGetOption(JNIEnv *env, jobject this,
- jint opt, jobject iaContainerObj) {
-
+Java_java_net_TwoStacksPlainSocketImpl_socketGetOption
+ (JNIEnv *env, jobject this, jint opt, jobject iaContainerObj)
+{
int fd, fd1;
int level = 0, optname = 0, optlen = 0;
union {
int i;
struct linger ling;
} optval;
+
/*
* Get SOCKET and check it hasn't been closed
*/
@@ -1073,7 +1072,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketGetOption(JNIEnv *env, jobject this
* level and option name.
*/
if (NET_MapSocketOption(opt, &level, &optname)) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
+ JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
return -1;
}
diff --git a/jdk/src/java.base/windows/native/libnet/net_util_md.c b/jdk/src/java.base/windows/native/libnet/net_util_md.c
index 4868201c1f3..963a5c7ad1e 100644
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.c
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c
@@ -202,19 +202,6 @@ NET_ThrowCurrent(JNIEnv *env, char *msg)
NET_ThrowNew(env, WSAGetLastError(), msg);
}
-void
-NET_ThrowSocketException(JNIEnv *env, char* msg)
-{
- static jclass cls = NULL;
- if (cls == NULL) {
- cls = (*env)->FindClass(env, "java/net/SocketException");
- CHECK_NULL(cls);
- cls = (*env)->NewGlobalRef(env, cls);
- CHECK_NULL(cls);
- }
- (*env)->ThrowNew(env, cls, msg);
-}
-
void
NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
const char *defaultDetail) {
diff --git a/jdk/src/java.base/windows/native/libnet/net_util_md.h b/jdk/src/java.base/windows/native/libnet/net_util_md.h
index 5ac48046f3b..be107e0a3b4 100644
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.h
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -299,8 +299,6 @@ int NET_Socket(int domain, int type, int protocol);
void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
const char *defaultDetail);
-void NET_ThrowSocketException(JNIEnv *env, char* msg);
-
/*
* differs from NET_Timeout() as follows:
*
diff --git a/jdk/src/java.desktop/share/classes/com/sun/beans/finder/ConstructorFinder.java b/jdk/src/java.desktop/share/classes/com/sun/beans/finder/ConstructorFinder.java
index 984bf8ad239..d0315ada6bf 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/beans/finder/ConstructorFinder.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/beans/finder/ConstructorFinder.java
@@ -67,19 +67,22 @@ public final class ConstructorFinder extends AbstractFinder> {
*/
public static Constructor> findConstructor(Class> type, Class>...args) throws NoSuchMethodException {
if (type.isPrimitive()) {
- throw new NoSuchMethodException("Primitive wrapper does not contain constructors");
+ throw new NoSuchMethodException("Primitive wrapper does not contain constructors: "
+ + type.getName());
}
if (type.isInterface()) {
- throw new NoSuchMethodException("Interface does not contain constructors");
+ throw new NoSuchMethodException("Interface does not contain constructors: "
+ + type.getName());
}
if (!FinderUtils.isExported(type)) {
- throw new NoSuchMethodException("Class is not accessible");
+ throw new NoSuchMethodException("Class is not accessible: " + type.getName());
}
if (Modifier.isAbstract(type.getModifiers())) {
- throw new NoSuchMethodException("Abstract class cannot be instantiated");
+ throw new NoSuchMethodException("Abstract class cannot be instantiated: "
+ + type.getName());
}
if (!Modifier.isPublic(type.getModifiers()) || !isPackageAccessible(type)) {
- throw new NoSuchMethodException("Class is not accessible");
+ throw new NoSuchMethodException("Class is not accessible: " + type.getName());
}
PrimitiveWrapperMap.replacePrimitivesWithWrappers(args);
Signature signature = new Signature(type, args);
diff --git a/jdk/src/java.desktop/share/classes/java/beans/MetaData.java b/jdk/src/java.desktop/share/classes/java/beans/MetaData.java
index 4110064bcd0..1443ce2b54f 100644
--- a/jdk/src/java.desktop/share/classes/java/beans/MetaData.java
+++ b/jdk/src/java.desktop/share/classes/java/beans/MetaData.java
@@ -510,102 +510,6 @@ private abstract static class java_util_Collections extends PersistenceDelegate
return new Expression(oldInstance, Collections.class, "synchronizedSortedMap", new Object[]{map});
}
}
-
- static final class CheckedCollection_PersistenceDelegate extends java_util_Collections {
- protected Expression instantiate(Object oldInstance, Encoder out) {
- Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
- List> list = new ArrayList<>((Collection>) oldInstance);
- return new Expression(oldInstance, Collections.class, "checkedCollection", new Object[]{list, type});
- }
- }
-
- static final class CheckedList_PersistenceDelegate extends java_util_Collections {
- protected Expression instantiate(Object oldInstance, Encoder out) {
- Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
- List> list = new LinkedList<>((Collection>) oldInstance);
- return new Expression(oldInstance, Collections.class, "checkedList", new Object[]{list, type});
- }
- }
-
- static final class CheckedRandomAccessList_PersistenceDelegate extends java_util_Collections {
- protected Expression instantiate(Object oldInstance, Encoder out) {
- Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
- List> list = new ArrayList<>((Collection>) oldInstance);
- return new Expression(oldInstance, Collections.class, "checkedList", new Object[]{list, type});
- }
- }
-
- static final class CheckedSet_PersistenceDelegate extends java_util_Collections {
- protected Expression instantiate(Object oldInstance, Encoder out) {
- Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
- Set> set = new HashSet<>((Set>) oldInstance);
- return new Expression(oldInstance, Collections.class, "checkedSet", new Object[]{set, type});
- }
- }
-
- static final class CheckedSortedSet_PersistenceDelegate extends java_util_Collections {
- protected Expression instantiate(Object oldInstance, Encoder out) {
- Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
- SortedSet> set = new TreeSet<>((SortedSet>) oldInstance);
- return new Expression(oldInstance, Collections.class, "checkedSortedSet", new Object[]{set, type});
- }
- }
-
- static final class CheckedMap_PersistenceDelegate extends java_util_Collections {
- protected Expression instantiate(Object oldInstance, Encoder out) {
- Object keyType = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.keyType");
- Object valueType = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.valueType");
- Map,?> map = new HashMap<>((Map,?>) oldInstance);
- return new Expression(oldInstance, Collections.class, "checkedMap", new Object[]{map, keyType, valueType});
- }
- }
-
- static final class CheckedSortedMap_PersistenceDelegate extends java_util_Collections {
- protected Expression instantiate(Object oldInstance, Encoder out) {
- Object keyType = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.keyType");
- Object valueType = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.valueType");
- SortedMap,?> map = new TreeMap<>((SortedMap,?>) oldInstance);
- return new Expression(oldInstance, Collections.class, "checkedSortedMap", new Object[]{map, keyType, valueType});
- }
- }
-}
-
-/**
- * The persistence delegate for {@code java.util.EnumMap} classes.
- *
- * @author Sergey A. Malenkov
- */
-static final class java_util_EnumMap_PersistenceDelegate extends PersistenceDelegate {
- protected boolean mutatesTo(Object oldInstance, Object newInstance) {
- return super.mutatesTo(oldInstance, newInstance) && (getType(oldInstance) == getType(newInstance));
- }
-
- protected Expression instantiate(Object oldInstance, Encoder out) {
- return new Expression(oldInstance, EnumMap.class, "new", new Object[] {getType(oldInstance)});
- }
-
- private static Object getType(Object instance) {
- return MetaData.getPrivateFieldValue(instance, "java.util.EnumMap.keyType");
- }
-}
-
-/**
- * The persistence delegate for {@code java.util.EnumSet} classes.
- *
- * @author Sergey A. Malenkov
- */
-static final class java_util_EnumSet_PersistenceDelegate extends PersistenceDelegate {
- protected boolean mutatesTo(Object oldInstance, Object newInstance) {
- return super.mutatesTo(oldInstance, newInstance) && (getType(oldInstance) == getType(newInstance));
- }
-
- protected Expression instantiate(Object oldInstance, Encoder out) {
- return new Expression(oldInstance, EnumSet.class, "noneOf", new Object[] {getType(oldInstance)});
- }
-
- private static Object getType(Object instance) {
- return MetaData.getPrivateFieldValue(instance, "java.util.EnumSet.elementType");
- }
}
// Collection
@@ -1313,9 +1217,6 @@ static final class sun_swing_PrintColorUIResource_PersistenceDelegate extends Pe
internalPersistenceDelegates.put("java.sql.Date", new java_util_Date_PersistenceDelegate());
internalPersistenceDelegates.put("java.sql.Time", new java_util_Date_PersistenceDelegate());
-
- internalPersistenceDelegates.put("java.util.JumboEnumSet", new java_util_EnumSet_PersistenceDelegate());
- internalPersistenceDelegates.put("java.util.RegularEnumSet", new java_util_EnumSet_PersistenceDelegate());
}
@SuppressWarnings("rawtypes")
diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/ImageReader.java b/jdk/src/java.desktop/share/classes/javax/imageio/ImageReader.java
index 5f39ea935fa..e17a5f2e796 100644
--- a/jdk/src/java.desktop/share/classes/javax/imageio/ImageReader.java
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/ImageReader.java
@@ -2461,16 +2461,16 @@ public abstract class ImageReader {
try {
bundle = ResourceBundle.getBundle(baseName, locale, this.getClass().getModule());
} catch (MissingResourceException mre) {
- throw new IllegalArgumentException("Bundle not found!");
+ throw new IllegalArgumentException("Bundle not found!", mre);
}
String warning = null;
try {
warning = bundle.getString(keyword);
} catch (ClassCastException cce) {
- throw new IllegalArgumentException("Resource is not a String!");
+ throw new IllegalArgumentException("Resource is not a String!", cce);
} catch (MissingResourceException mre) {
- throw new IllegalArgumentException("Resource is missing!");
+ throw new IllegalArgumentException("Resource is missing!", mre);
}
listener.warningOccurred(this, warning);
diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/ImageWriter.java b/jdk/src/java.desktop/share/classes/javax/imageio/ImageWriter.java
index a9a681ce05f..8723c50773e 100644
--- a/jdk/src/java.desktop/share/classes/javax/imageio/ImageWriter.java
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/ImageWriter.java
@@ -1963,16 +1963,16 @@ public abstract class ImageWriter implements ImageTranscoder {
try {
bundle = ResourceBundle.getBundle(baseName, locale, this.getClass().getModule());
} catch (MissingResourceException mre) {
- throw new IllegalArgumentException("Bundle not found!");
+ throw new IllegalArgumentException("Bundle not found!", mre);
}
String warning = null;
try {
warning = bundle.getString(keyword);
} catch (ClassCastException cce) {
- throw new IllegalArgumentException("Resource is not a String!");
+ throw new IllegalArgumentException("Resource is not a String!", cce);
} catch (MissingResourceException mre) {
- throw new IllegalArgumentException("Resource is missing!");
+ throw new IllegalArgumentException("Resource is missing!", mre);
}
listener.warningOccurred(this, imageIndex, warning);
diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
index c1895cd29d7..7124f6127af 100644
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
@@ -442,7 +442,7 @@ getAllConfigs (JNIEnv *env, int screen, AwtScreenDataPtr screenDataPtr) {
#ifndef __linux__ /* SOLARIS */
if (xrenderLibHandle == NULL) {
- xrenderLibHandle = dlopen("/usr/sfw/lib/libXrender.so.1",
+ xrenderLibHandle = dlopen("/usr/lib/libXrender.so.1",
RTLD_LAZY | RTLD_GLOBAL);
}
#endif
diff --git a/jdk/src/java.desktop/unix/native/libjawt/jawt.c b/jdk/src/java.desktop/unix/native/libjawt/jawt.c
index 59e9a55cff2..ee61138dd31 100644
--- a/jdk/src/java.desktop/unix/native/libjawt/jawt.c
+++ b/jdk/src/java.desktop/unix/native/libjawt/jawt.c
@@ -39,6 +39,10 @@ DEF_STATIC_JNI_OnLoad
*/
JNIEXPORT jboolean JNICALL JAWT_GetAWT(JNIEnv* env, JAWT* awt)
{
+#if defined(HEADLESS)
+ /* there are no AWT libs available at all */
+ return JNI_FALSE;
+#else
if (awt == NULL) {
return JNI_FALSE;
}
@@ -64,4 +68,5 @@ JNIEXPORT jboolean JNICALL JAWT_GetAWT(JNIEnv* env, JAWT* awt)
}
return JNI_TRUE;
+#endif
}
diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java
index 022dc3be72a..f7eef204357 100644
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -344,7 +344,7 @@ final class P11Cipher extends CipherSpi {
private void implInit(int opmode, Key key, byte[] iv,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
- cancelOperation();
+ reset(true);
if (fixedKeySize != -1 && key.getEncoded().length != fixedKeySize) {
throw new InvalidKeyException("Key size is invalid");
}
@@ -404,23 +404,26 @@ final class P11Cipher extends CipherSpi {
if (initialized == false) {
return;
}
- initialized = false;
+
if ((session == null) || (token.explicitCancel == false)) {
return;
}
- // cancel operation by finishing it
- int bufLen = doFinalLength(0);
- byte[] buffer = new byte[bufLen];
try {
- if (encrypt) {
- token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen);
+ if (session.hasObjects() == false) {
+ session = token.killSession(session);
+ return;
} else {
- token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
+ // cancel operation by finishing it
+ int bufLen = doFinalLength(0);
+ byte[] buffer = new byte[bufLen];
+ if (encrypt) {
+ token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen);
+ } else {
+ token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
+ }
}
} catch (PKCS11Exception e) {
throw new ProviderException("Cancel failed", e);
- } finally {
- reset();
}
}
@@ -483,7 +486,9 @@ final class P11Cipher extends CipherSpi {
}
// reset the states to the pre-initialized values
- private void reset() {
+ private void reset(boolean doCancel) {
+ if (doCancel) cancelOperation();
+
initialized = false;
bytesBuffered = 0;
padBufferLen = 0;
@@ -610,7 +615,7 @@ final class P11Cipher extends CipherSpi {
throw (ShortBufferException)
(new ShortBufferException().initCause(e));
}
- reset();
+ reset(false);
throw new ProviderException("update() failed", e);
}
}
@@ -728,7 +733,7 @@ final class P11Cipher extends CipherSpi {
throw (ShortBufferException)
(new ShortBufferException().initCause(e));
}
- reset();
+ reset(false);
throw new ProviderException("update() failed", e);
}
}
@@ -740,6 +745,7 @@ final class P11Cipher extends CipherSpi {
if (outLen < requiredOutLen) {
throw new ShortBufferException();
}
+ boolean doCancel = true;
try {
ensureInitialized();
int k = 0;
@@ -753,7 +759,12 @@ final class P11Cipher extends CipherSpi {
}
k += token.p11.C_EncryptFinal(session.id(),
0, out, (outOfs + k), (outLen - k));
+ doCancel = false;
} else {
+ // Special handling to match SunJCE provider behavior
+ if (bytesBuffered == 0 && padBufferLen == 0) {
+ return 0;
+ }
if (paddingObj != null) {
if (padBufferLen != 0) {
k = token.p11.C_DecryptUpdate(session.id(), 0,
@@ -762,20 +773,24 @@ final class P11Cipher extends CipherSpi {
}
k += token.p11.C_DecryptFinal(session.id(), 0, padBuffer, k,
padBuffer.length - k);
+ doCancel = false;
+
int actualPadLen = paddingObj.unpad(padBuffer, k);
k -= actualPadLen;
System.arraycopy(padBuffer, 0, out, outOfs, k);
} else {
k = token.p11.C_DecryptFinal(session.id(), 0, out, outOfs,
outLen);
+ doCancel = false;
}
}
return k;
} catch (PKCS11Exception e) {
+ doCancel = false;
handleException(e);
throw new ProviderException("doFinal() failed", e);
} finally {
- reset();
+ reset(doCancel);
}
}
@@ -788,6 +803,7 @@ final class P11Cipher extends CipherSpi {
throw new ShortBufferException();
}
+ boolean doCancel = true;
try {
ensureInitialized();
@@ -818,7 +834,13 @@ final class P11Cipher extends CipherSpi {
}
k += token.p11.C_EncryptFinal(session.id(),
outAddr, outArray, (outOfs + k), (outLen - k));
+ doCancel = false;
} else {
+ // Special handling to match SunJCE provider behavior
+ if (bytesBuffered == 0 && padBufferLen == 0) {
+ return 0;
+ }
+
if (paddingObj != null) {
if (padBufferLen != 0) {
k = token.p11.C_DecryptUpdate(session.id(),
@@ -828,6 +850,8 @@ final class P11Cipher extends CipherSpi {
}
k += token.p11.C_DecryptFinal(session.id(),
0, padBuffer, k, padBuffer.length - k);
+ doCancel = false;
+
int actualPadLen = paddingObj.unpad(padBuffer, k);
k -= actualPadLen;
outArray = padBuffer;
@@ -835,6 +859,7 @@ final class P11Cipher extends CipherSpi {
} else {
k = token.p11.C_DecryptFinal(session.id(),
outAddr, outArray, outOfs, outLen);
+ doCancel = false;
}
}
if ((!encrypt && paddingObj != null) ||
@@ -846,10 +871,11 @@ final class P11Cipher extends CipherSpi {
}
return k;
} catch (PKCS11Exception e) {
+ doCancel = false;
handleException(e);
throw new ProviderException("doFinal() failed", e);
} finally {
- reset();
+ reset(doCancel);
}
}
diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Signature.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Signature.java
index 953a07bfd0b..43dfcd6a0b0 100644
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Signature.java
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Signature.java
@@ -616,8 +616,11 @@ final class P11Signature extends SignatureSpi {
return dsaToASN1(signature);
}
}
- } catch (PKCS11Exception e) {
- throw new ProviderException(e);
+ } catch (PKCS11Exception pe) {
+ throw new ProviderException(pe);
+ } catch (SignatureException | ProviderException e) {
+ cancelOperation();
+ throw e;
} finally {
initialized = false;
session = token.releaseSession(session);
@@ -669,8 +672,8 @@ final class P11Signature extends SignatureSpi {
}
}
return true;
- } catch (PKCS11Exception e) {
- long errorCode = e.getErrorCode();
+ } catch (PKCS11Exception pe) {
+ long errorCode = pe.getErrorCode();
if (errorCode == CKR_SIGNATURE_INVALID) {
return false;
}
@@ -682,10 +685,11 @@ final class P11Signature extends SignatureSpi {
if (errorCode == CKR_DATA_LEN_RANGE) {
return false;
}
- throw new ProviderException(e);
+ throw new ProviderException(pe);
+ } catch (SignatureException | ProviderException e) {
+ cancelOperation();
+ throw e;
} finally {
- // XXX we should not release the session if we abort above
- // before calling C_Verify
initialized = false;
session = token.releaseSession(session);
}
diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java
index c054f312c55..83ecaa1701f 100644
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -68,8 +68,8 @@ public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi {
// master secret as a P11Key
private P11Key p11Key;
- // version, e.g. 0x0301
- private int version;
+ // whether SSLv3 is supported
+ private final boolean supportSSLv3;
P11TlsKeyMaterialGenerator(Token token, String algorithm, long mechanism)
throws PKCS11Exception {
@@ -77,6 +77,11 @@ public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi {
this.token = token;
this.algorithm = algorithm;
this.mechanism = mechanism;
+
+ // Given the current lookup order specified in SunPKCS11.java,
+ // if CKM_SSL3_KEY_AND_MAC_DERIVE is not used to construct this object,
+ // it means that this mech is disabled or unsupported.
+ this.supportSSLv3 = (mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE);
}
protected void engineInit(SecureRandom random) {
@@ -89,20 +94,26 @@ public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi {
if (params instanceof TlsKeyMaterialParameterSpec == false) {
throw new InvalidAlgorithmParameterException(MSG);
}
- this.spec = (TlsKeyMaterialParameterSpec)params;
+
+ TlsKeyMaterialParameterSpec spec = (TlsKeyMaterialParameterSpec)params;
+ int version = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
+
+ if ((version == 0x0300 && !supportSSLv3) || (version < 0x0300) ||
+ (version > 0x0302)) {
+ throw new InvalidAlgorithmParameterException
+ ("Only" + (supportSSLv3? " SSL 3.0,": "") +
+ " TLS 1.0, and TLS 1.1 are supported (0x" +
+ Integer.toHexString(version) + ")");
+ }
try {
p11Key = P11SecretKeyFactory.convertKey
(token, spec.getMasterSecret(), "TlsMasterSecret");
} catch (InvalidKeyException e) {
throw new InvalidAlgorithmParameterException("init() failed", e);
}
- version = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
- if ((version < 0x0300) && (version > 0x0302)) {
- throw new InvalidAlgorithmParameterException
- ("Only SSL 3.0, TLS 1.0, and TLS 1.1 are supported");
- }
- // we assume the token supports both the CKM_SSL3_* and the CKM_TLS_*
- // mechanisms
+ this.spec = spec;
+ this.mechanism = (version == 0x0300)?
+ CKM_SSL3_KEY_AND_MAC_DERIVE : CKM_TLS_KEY_AND_MAC_DERIVE;
}
protected void engineInit(int keysize, SecureRandom random) {
@@ -115,8 +126,6 @@ public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi {
throw new IllegalStateException
("TlsKeyMaterialGenerator must be initialized");
}
- mechanism = (version == 0x0300) ? CKM_SSL3_KEY_AND_MAC_DERIVE
- : CKM_TLS_KEY_AND_MAC_DERIVE;
int macBits = spec.getMacKeyLength() << 3;
int ivBits = spec.getIvLength() << 3;
diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java
index 73a2ac2e890..128952e8a49 100644
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,10 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
private TlsMasterSecretParameterSpec spec;
private P11Key p11Key;
- int version;
+ CK_VERSION ckVersion;
+
+ // whether SSLv3 is supported
+ private final boolean supportSSLv3;
P11TlsMasterSecretGenerator(Token token, String algorithm, long mechanism)
throws PKCS11Exception {
@@ -69,6 +72,11 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
this.token = token;
this.algorithm = algorithm;
this.mechanism = mechanism;
+
+ // Given the current lookup order specified in SunPKCS11.java, if
+ // CKM_SSL3_MASTER_KEY_DERIVE is not used to construct this object,
+ // it means that this mech is disabled or unsupported.
+ supportSSLv3 = (mechanism == CKM_SSL3_MASTER_KEY_DERIVE);
}
protected void engineInit(SecureRandom random) {
@@ -81,7 +89,17 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
if (params instanceof TlsMasterSecretParameterSpec == false) {
throw new InvalidAlgorithmParameterException(MSG);
}
- this.spec = (TlsMasterSecretParameterSpec)params;
+
+ TlsMasterSecretParameterSpec spec = (TlsMasterSecretParameterSpec)params;
+ int version = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
+ if ((version == 0x0300 && !supportSSLv3) || (version < 0x0300) ||
+ (version > 0x0302)) {
+ throw new InvalidAlgorithmParameterException
+ ("Only" + (supportSSLv3? " SSL 3.0,": "") +
+ " TLS 1.0, and TLS 1.1 are supported (0x" +
+ Integer.toHexString(version) + ")");
+ }
+
SecretKey key = spec.getPremasterSecret();
// algorithm should be either TlsRsaPremasterSecret or TlsPremasterSecret,
// but we omit the check
@@ -90,25 +108,7 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
} catch (InvalidKeyException e) {
throw new InvalidAlgorithmParameterException("init() failed", e);
}
- version = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
- if ((version < 0x0300) || (version > 0x0302)) {
- throw new InvalidAlgorithmParameterException
- ("Only SSL 3.0, TLS 1.0, and TLS 1.1 supported");
- }
- // We assume the token supports the required mechanism. If it does not,
- // generateKey() will fail and the failover should take care of us.
- }
-
- protected void engineInit(int keysize, SecureRandom random) {
- throw new InvalidParameterException(MSG);
- }
-
- protected SecretKey engineGenerateKey() {
- if (spec == null) {
- throw new IllegalStateException
- ("TlsMasterSecretGenerator must be initialized");
- }
- CK_VERSION ckVersion;
+ this.spec = spec;
if (p11Key.getAlgorithm().equals("TlsRsaPremasterSecret")) {
mechanism = (version == 0x0300) ? CKM_SSL3_MASTER_KEY_DERIVE
: CKM_TLS_MASTER_KEY_DERIVE;
@@ -124,6 +124,17 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
: CKM_TLS_MASTER_KEY_DERIVE_DH;
ckVersion = null;
}
+ }
+
+ protected void engineInit(int keysize, SecureRandom random) {
+ throw new InvalidParameterException(MSG);
+ }
+
+ protected SecretKey engineGenerateKey() {
+ if (spec == null) {
+ throw new IllegalStateException
+ ("TlsMasterSecretGenerator must be initialized");
+ }
byte[] clientRandom = spec.getClientRandom();
byte[] serverRandom = spec.getServerRandom();
CK_SSL3_RANDOM_DATA random =
@@ -139,13 +150,12 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
long keyID = token.p11.C_DeriveKey(session.id(),
new CK_MECHANISM(mechanism, params), p11Key.keyID, attributes);
int major, minor;
- ckVersion = params.pVersion;
- if (ckVersion == null) {
+ if (params.pVersion == null) {
major = -1;
minor = -1;
} else {
- major = ckVersion.major;
- minor = ckVersion.minor;
+ major = params.pVersion.major;
+ minor = params.pVersion.minor;
}
SecretKey key = P11Key.masterSecretKey(session, keyID,
"TlsMasterSecret", 48 << 3, attributes, major, minor);
@@ -156,5 +166,4 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
token.releaseSession(session);
}
}
-
}
diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java
index 40d3a634ce5..245c067b3d4 100644
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -60,12 +60,20 @@ final class P11TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
@SuppressWarnings("deprecation")
private TlsRsaPremasterSecretParameterSpec spec;
+ // whether SSLv3 is supported
+ private final boolean supportSSLv3;
+
P11TlsRsaPremasterSecretGenerator(Token token, String algorithm, long mechanism)
throws PKCS11Exception {
super();
this.token = token;
this.algorithm = algorithm;
this.mechanism = mechanism;
+
+ // Given the current lookup order specified in SunPKCS11.java,
+ // if CKM_SSL3_PRE_MASTER_KEY_GEN is not used to construct this object,
+ // it means that this mech is disabled or unsupported.
+ this.supportSSLv3 = (mechanism == CKM_SSL3_PRE_MASTER_KEY_GEN);
}
protected void engineInit(SecureRandom random) {
@@ -78,7 +86,20 @@ final class P11TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
throw new InvalidAlgorithmParameterException(MSG);
}
- this.spec = (TlsRsaPremasterSecretParameterSpec)params;
+
+ TlsRsaPremasterSecretParameterSpec spec =
+ (TlsRsaPremasterSecretParameterSpec) params;
+
+ int version = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
+
+ if ((version == 0x0300 && !supportSSLv3) || (version < 0x0300) ||
+ (version > 0x0302)) {
+ throw new InvalidAlgorithmParameterException
+ ("Only" + (supportSSLv3? " SSL 3.0,": "") +
+ " TLS 1.0, and TLS 1.1 are supported (0x" +
+ Integer.toHexString(version) + ")");
+ }
+ this.spec = spec;
}
protected void engineInit(int keysize, SecureRandom random) {
diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Secmod.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Secmod.java
index cd11ad57fe9..2059e4bc5bf 100644
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Secmod.java
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Secmod.java
@@ -45,7 +45,7 @@ import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
*
* Secmod secmod = Secmod.getInstance();
* if (secmod.isInitialized() == false) {
- * secmod.initialize("/home/myself/.mozilla", "/usr/sfw/lib/mozilla");
+ * secmod.initialize("/home/myself/.mozilla");
* }
*
* Provider p = secmod.getModule(ModuleType.KEYSTORE).getProvider();
@@ -743,6 +743,7 @@ public final class Secmod {
Map trustMap = new HashMap();
Token token = provider.getToken();
Session session = null;
+ boolean exceptionOccurred = true;
try {
session = token.getOpSession();
int MAX_NUM = 8192;
@@ -762,8 +763,13 @@ public final class Secmod {
// skip put on pkcs11 error
}
}
+ exceptionOccurred = false;
} finally {
- token.releaseSession(session);
+ if (exceptionOccurred) {
+ token.killSession(session);
+ } else {
+ token.releaseSession(session);
+ }
}
return trustMap;
}
diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipherWithJavaPadding.java b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipherWithJavaPadding.java
index 4d36710ab0d..56ddee9726b 100644
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipherWithJavaPadding.java
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipherWithJavaPadding.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -160,8 +160,11 @@ public class NativeCipherWithJavaPadding extends CipherSpi {
ShortBufferException {
int tbSize = (trailingBytes == null? 0:trailingBytes.position());
int dataLen = tbSize + lastData.length;
- // check total length
- if ((dataLen < 1) || (dataLen % blockSize != 0)) {
+
+ // Special handling to match SunJCE provider behavior
+ if (dataLen <= 0) {
+ return 0;
+ } else if (dataLen % blockSize != 0) {
UcryptoProvider.debug("PKCS5Padding: unpad, buffered " + tbSize +
" bytes, last block " + lastData.length + " bytes");
@@ -402,7 +405,6 @@ public class NativeCipherWithJavaPadding extends CipherSpi {
throws ShortBufferException, IllegalBlockSizeException,
BadPaddingException {
int estimatedOutLen = engineGetOutputSize(inLen);
-
if (out.length - outOfs < estimatedOutLen) {
throw new ShortBufferException("Actual: " + (out.length - outOfs) +
". Estimated Out Length: " + estimatedOutLen);
diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSASignature.java b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSASignature.java
index ffdf51f0379..d8dd9535911 100644
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSASignature.java
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSASignature.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -258,27 +258,38 @@ class NativeRSASignature extends SignatureSpi {
@Override
protected synchronized byte[] engineSign() throws SignatureException {
- byte[] sig = new byte[sigLength];
- int rv = doFinal(sig, 0, sigLength);
- if (rv < 0) {
- throw new SignatureException(new UcryptoException(-rv));
+ try {
+ byte[] sig = new byte[sigLength];
+ int rv = doFinal(sig, 0, sigLength);
+ if (rv < 0) {
+ throw new SignatureException(new UcryptoException(-rv));
+ }
+ return sig;
+ } finally {
+ // doFinal should already be called, no need to cancel
+ reset(false);
}
- return sig;
}
@Override
protected synchronized int engineSign(byte[] outbuf, int offset, int len)
throws SignatureException {
- if (outbuf == null || (offset < 0) || (outbuf.length < (offset + sigLength))
- || (len < sigLength)) {
- throw new SignatureException("Invalid output buffer. offset: " +
- offset + ". len: " + len + ". sigLength: " + sigLength);
+ boolean doCancel = true;
+ try {
+ if (outbuf == null || (offset < 0) || (outbuf.length < (offset + sigLength))
+ || (len < sigLength)) {
+ throw new SignatureException("Invalid output buffer. offset: " +
+ offset + ". len: " + len + ". sigLength: " + sigLength);
+ }
+ int rv = doFinal(outbuf, offset, sigLength);
+ doCancel = false;
+ if (rv < 0) {
+ throw new SignatureException(new UcryptoException(-rv));
+ }
+ return sigLength;
+ } finally {
+ reset(doCancel);
}
- int rv = doFinal(outbuf, offset, sigLength);
- if (rv < 0) {
- throw new SignatureException(new UcryptoException(-rv));
- }
- return sigLength;
}
@Override
@@ -329,19 +340,25 @@ class NativeRSASignature extends SignatureSpi {
@Override
protected synchronized boolean engineVerify(byte[] sigBytes, int sigOfs, int sigLen)
throws SignatureException {
- if (sigBytes == null || (sigOfs < 0) || (sigBytes.length < (sigOfs + this.sigLength))
- || (sigLen != this.sigLength)) {
- throw new SignatureException("Invalid signature length: got " +
- sigLen + " but was expecting " + this.sigLength);
- }
+ boolean doCancel = true;
+ try {
+ if (sigBytes == null || (sigOfs < 0) || (sigBytes.length < (sigOfs + this.sigLength))
+ || (sigLen != this.sigLength)) {
+ throw new SignatureException("Invalid signature length: got " +
+ sigLen + " but was expecting " + this.sigLength);
+ }
- int rv = doFinal(sigBytes, sigOfs, sigLen);
- if (rv == 0) {
- return true;
- } else {
- UcryptoProvider.debug("Signature: " + mech + " verification error " +
+ int rv = doFinal(sigBytes, sigOfs, sigLen);
+ doCancel = false;
+ if (rv == 0) {
+ return true;
+ } else {
+ UcryptoProvider.debug("Signature: " + mech + " verification error " +
new UcryptoException(-rv).getMessage());
- return false;
+ return false;
+ }
+ } finally {
+ reset(doCancel);
}
}
@@ -432,13 +449,9 @@ class NativeRSASignature extends SignatureSpi {
// returns 0 (success) or negative (ucrypto error occurred)
private int doFinal(byte[] sigBytes, int sigOfs, int sigLen) {
- try {
- ensureInitialized();
- int k = nativeFinal(pCtxt.id, sign, sigBytes, sigOfs, sigLen);
- return k;
- } finally {
- reset(false);
- }
+ ensureInitialized();
+ int k = nativeFinal(pCtxt.id, sign, sigBytes, sigOfs, sigLen);
+ return k;
}
// check and return RSA key size in number of bytes
diff --git a/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/extra/EditingHistory.java b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/extra/EditingHistory.java
index 1bcccc0ded8..394d0eb4096 100644
--- a/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/extra/EditingHistory.java
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/extra/EditingHistory.java
@@ -48,7 +48,9 @@ public abstract class EditingHistory implements History {
private History currentDelegate;
protected EditingHistory(ConsoleReader in, Iterable extends String> originalHistory) {
- this.fullHistory = new MemoryHistory();
+ MemoryHistory fullHistory = new MemoryHistory();
+ fullHistory.setIgnoreDuplicates(false);
+ this.fullHistory = fullHistory;
this.currentDelegate = fullHistory;
bind(in, CTRL_UP,
(Runnable) () -> moveHistoryToSnippet(in, ((EditingHistory) in.getHistory())::previousSnippet));
diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c
index 3baf486c233..c6078a79d78 100644
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c
@@ -211,6 +211,62 @@ createGlobalRefs(JNIEnv *env, InvokeRequest *request)
return error;
}
+/*
+ * Delete saved global references - if any - for:
+ * - a potentially thrown Exception
+ * - a returned refernce/array value
+ * See invoker_doInvoke() and invoke* methods where global references
+ * are being saved.
+ */
+static void
+deletePotentiallySavedGlobalRefs(JNIEnv *env, InvokeRequest *request)
+{
+ /* Delete potentially saved return value */
+ if ((request->invokeType == INVOKE_CONSTRUCTOR) ||
+ (returnTypeTag(request->methodSignature) == JDWP_TAG(OBJECT)) ||
+ (returnTypeTag(request->methodSignature) == JDWP_TAG(ARRAY))) {
+ if (request->returnValue.l != NULL) {
+ tossGlobalRef(env, &(request->returnValue.l));
+ }
+ }
+ /* Delete potentially saved exception */
+ if (request->exception != NULL) {
+ tossGlobalRef(env, &(request->exception));
+ }
+}
+
+/*
+ * Delete global argument references from the request which got put there before a
+ * invoke request was carried out. See fillInvokeRequest().
+ */
+static void
+deleteGlobalArgumentRefs(JNIEnv *env, InvokeRequest *request)
+{
+ void *cursor;
+ jint argIndex = 0;
+ jvalue *argument = request->arguments;
+ jbyte argumentTag = firstArgumentTypeTag(request->methodSignature, &cursor);
+
+ if (request->clazz != NULL) {
+ tossGlobalRef(env, &(request->clazz));
+ }
+ if (request->instance != NULL) {
+ tossGlobalRef(env, &(request->instance));
+ }
+ /* Delete global argument references */
+ while (argIndex < request->argumentCount) {
+ if ((argumentTag == JDWP_TAG(OBJECT)) ||
+ (argumentTag == JDWP_TAG(ARRAY))) {
+ if (argument->l != NULL) {
+ tossGlobalRef(env, &(argument->l));
+ }
+ }
+ argument++;
+ argIndex++;
+ argumentTag = nextArgumentTypeTag(&cursor);
+ }
+}
+
static jvmtiError
fillInvokeRequest(JNIEnv *env, InvokeRequest *request,
jbyte invokeType, jbyte options, jint id,
@@ -322,6 +378,8 @@ static void
invokeConstructor(JNIEnv *env, InvokeRequest *request)
{
jobject object;
+
+ JDI_ASSERT_MSG(request->clazz, "Request clazz null");
object = JNI_FUNC_PTR(env,NewObjectA)(env, request->clazz,
request->method,
request->arguments);
@@ -338,6 +396,7 @@ invokeStatic(JNIEnv *env, InvokeRequest *request)
case JDWP_TAG(OBJECT):
case JDWP_TAG(ARRAY): {
jobject object;
+ JDI_ASSERT_MSG(request->clazz, "Request clazz null");
object = JNI_FUNC_PTR(env,CallStaticObjectMethodA)(env,
request->clazz,
request->method,
@@ -426,6 +485,7 @@ invokeVirtual(JNIEnv *env, InvokeRequest *request)
case JDWP_TAG(OBJECT):
case JDWP_TAG(ARRAY): {
jobject object;
+ JDI_ASSERT_MSG(request->instance, "Request instance null");
object = JNI_FUNC_PTR(env,CallObjectMethodA)(env,
request->instance,
request->method,
@@ -513,6 +573,8 @@ invokeNonvirtual(JNIEnv *env, InvokeRequest *request)
case JDWP_TAG(OBJECT):
case JDWP_TAG(ARRAY): {
jobject object;
+ JDI_ASSERT_MSG(request->clazz, "Request clazz null");
+ JDI_ASSERT_MSG(request->instance, "Request instance null");
object = JNI_FUNC_PTR(env,CallNonvirtualObjectMethodA)(env,
request->instance,
request->clazz,
@@ -609,6 +671,8 @@ invoker_doInvoke(jthread thread)
JNIEnv *env;
jboolean startNow;
InvokeRequest *request;
+ jbyte options;
+ jbyte invokeType;
JDI_ASSERT(thread);
@@ -625,6 +689,9 @@ invoker_doInvoke(jthread thread)
if (startNow) {
request->started = JNI_TRUE;
}
+ options = request->options;
+ invokeType = request->invokeType;
+
debugMonitorExit(invokerLock);
if (!startNow) {
@@ -639,7 +706,7 @@ invoker_doInvoke(jthread thread)
JNI_FUNC_PTR(env,ExceptionClear)(env);
- switch (request->invokeType) {
+ switch (invokeType) {
case INVOKE_CONSTRUCTOR:
invokeConstructor(env, request);
break;
@@ -647,7 +714,7 @@ invoker_doInvoke(jthread thread)
invokeStatic(env, request);
break;
case INVOKE_INSTANCE:
- if (request->options & JDWP_INVOKE_OPTIONS(NONVIRTUAL) ) {
+ if (options & JDWP_INVOKE_OPTIONS(NONVIRTUAL) ) {
invokeNonvirtual(env, request);
} else {
invokeVirtual(env, request);
@@ -724,13 +791,24 @@ invoker_completeInvokeRequest(jthread thread)
returnValue = request->returnValue;
}
+ /*
+ * At this time, there's no need to retain global references on
+ * arguments since the reply is processed. No one will deal with
+ * this request ID anymore, so we must call deleteGlobalArgumentRefs().
+ *
+ * We cannot delete saved exception or return value references
+ * since otherwise a deleted handle would escape when writing
+ * the response to the stream. Instead, we clean those refs up
+ * after writing the respone.
+ */
+ deleteGlobalArgumentRefs(env, request);
+
/*
* Give up the lock before I/O operation
*/
debugMonitorExit(invokerLock);
eventHandler_unlock();
-
if (!detached) {
outStream_initReply(&out, id);
(void)outStream_writeValue(env, &out, tag, returnValue);
@@ -738,6 +816,16 @@ invoker_completeInvokeRequest(jthread thread)
(void)outStream_writeObjectRef(env, &out, exc);
outStream_sendReply(&out);
}
+
+ /*
+ * Delete potentially saved global references of return value
+ * and exception
+ */
+ eventHandler_lock(); // for proper lock order
+ debugMonitorEnter(invokerLock);
+ deletePotentiallySavedGlobalRefs(env, request);
+ debugMonitorExit(invokerLock);
+ eventHandler_unlock();
}
jboolean
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java
index 1190a64abd7..dfecf9e0c3a 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java
@@ -86,6 +86,9 @@ public class JlinkTask {
task.options.help = true;
}, "--help", "-h"),
new Option(true, (task, opt, arg) -> {
+ // if used multiple times, the last one wins!
+ // So, clear previous values, if any.
+ task.options.modulePath.clear();
String[] dirs = arg.split(File.pathSeparator);
int i = 0;
Arrays.stream(dirs)
@@ -93,6 +96,9 @@ public class JlinkTask {
.forEach(task.options.modulePath::add);
}, "--module-path", "-p"),
new Option(true, (task, opt, arg) -> {
+ // if used multiple times, the last one wins!
+ // So, clear previous values, if any.
+ task.options.limitMods.clear();
for (String mn : arg.split(",")) {
if (mn.isEmpty()) {
throw taskHelper.newBadArgs("err.mods.must.be.specified",
diff --git a/jdk/src/jdk.management/share/native/libmanagement_ext/DiagnosticCommandImpl.c b/jdk/src/jdk.management/share/native/libmanagement_ext/DiagnosticCommandImpl.c
index f0267dd3ee3..90a30d95762 100644
--- a/jdk/src/jdk.management/share/native/libmanagement_ext/DiagnosticCommandImpl.c
+++ b/jdk/src/jdk.management/share/native/libmanagement_ext/DiagnosticCommandImpl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,13 @@ Java_com_sun_management_internal_DiagnosticCommandImpl_getDiagnosticCommands
return jmm_interface->GetDiagnosticCommands(env);
}
+#define EXCEPTION_CHECK_AND_FREE(x) do { \
+ if ((*env)->ExceptionCheck(env)) { \
+ free(x); \
+ return NULL; \
+ } \
+ } while(0)
+
jobject getDiagnosticCommandArgumentInfoArray(JNIEnv *env, jstring command,
int num_arg) {
int i;
@@ -59,6 +66,7 @@ jobject getDiagnosticCommandArgumentInfoArray(JNIEnv *env, jstring command,
dcmd_arg_info_array = (dcmdArgInfo*) malloc(num_arg * sizeof(dcmdArgInfo));
/* According to ISO C it is perfectly legal for malloc to return zero if called with a zero argument */
if (dcmd_arg_info_array == NULL && num_arg != 0) {
+ JNU_ThrowOutOfMemoryError(env, 0);
return NULL;
}
jmm_interface->GetDiagnosticCommandArgumentsInfo(env, command,
@@ -76,14 +84,24 @@ jobject getDiagnosticCommandArgumentInfoArray(JNIEnv *env, jstring command,
return NULL;
}
for (i=0; iNewStringUTF(env,dcmd_arg_info_array[i].name);
+ EXCEPTION_CHECK_AND_FREE(dcmd_arg_info_array);
+
+ jdesc = (*env)->NewStringUTF(env,dcmd_arg_info_array[i].description);
+ EXCEPTION_CHECK_AND_FREE(dcmd_arg_info_array);
+
+ jtype = (*env)->NewStringUTF(env,dcmd_arg_info_array[i].type);
+ EXCEPTION_CHECK_AND_FREE(dcmd_arg_info_array);
+
+ jdefStr = (*env)->NewStringUTF(env, dcmd_arg_info_array[i].default_string);
+ EXCEPTION_CHECK_AND_FREE(dcmd_arg_info_array);
obj = JNU_NewObjectByName(env,
"com/sun/management/internal/DiagnosticCommandArgumentInfo",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZI)V",
- (*env)->NewStringUTF(env,dcmd_arg_info_array[i].name),
- (*env)->NewStringUTF(env,dcmd_arg_info_array[i].description),
- (*env)->NewStringUTF(env,dcmd_arg_info_array[i].type),
- dcmd_arg_info_array[i].default_string == NULL ? NULL:
- (*env)->NewStringUTF(env, dcmd_arg_info_array[i].default_string),
+ jname, jdesc, jtype,
+ dcmd_arg_info_array[i].default_string == NULL ? NULL: jdefStr,
dcmd_arg_info_array[i].mandatory,
dcmd_arg_info_array[i].option,
dcmd_arg_info_array[i].multiple,
@@ -93,6 +111,7 @@ jobject getDiagnosticCommandArgumentInfoArray(JNIEnv *env, jstring command,
return NULL;
}
(*env)->SetObjectArrayElement(env, result, i, obj);
+ EXCEPTION_CHECK_AND_FREE(dcmd_arg_info_array);
}
free(dcmd_arg_info_array);
arraysCls = (*env)->FindClass(env, "java/util/Arrays");
@@ -125,6 +144,7 @@ Java_com_sun_management_internal_DiagnosticCommandImpl_getDiagnosticCommandInfo
jint ret = jmm_interface->GetOptionalSupport(env, &mos);
jsize num_commands;
dcmdInfo* dcmd_info_array;
+ jstring jname, jdesc, jimpact;
if (commands == NULL) {
JNU_ThrowNullPointerException(env, "Invalid String Array");
@@ -139,7 +159,6 @@ Java_com_sun_management_internal_DiagnosticCommandImpl_getDiagnosticCommandInfo
result = (*env)->NewObjectArray(env, num_commands, dcmdInfoCls, NULL);
if (result == NULL) {
- JNU_ThrowOutOfMemoryError(env, 0);
return NULL;
}
if (num_commands == 0) {
@@ -159,15 +178,22 @@ Java_com_sun_management_internal_DiagnosticCommandImpl_getDiagnosticCommandInfo
dcmd_info_array[i].num_arguments);
if (args == NULL) {
free(dcmd_info_array);
- JNU_ThrowOutOfMemoryError(env, 0);
return NULL;
}
+
+ jname = (*env)->NewStringUTF(env,dcmd_info_array[i].name);
+ EXCEPTION_CHECK_AND_FREE(dcmd_info_array);
+
+ jdesc = (*env)->NewStringUTF(env,dcmd_info_array[i].description);
+ EXCEPTION_CHECK_AND_FREE(dcmd_info_array);
+
+ jimpact = (*env)->NewStringUTF(env,dcmd_info_array[i].impact);
+ EXCEPTION_CHECK_AND_FREE(dcmd_info_array);
+
obj = JNU_NewObjectByName(env,
"com/sun/management/internal/DiagnosticCommandInfo",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLjava/util/List;)V",
- (*env)->NewStringUTF(env,dcmd_info_array[i].name),
- (*env)->NewStringUTF(env,dcmd_info_array[i].description),
- (*env)->NewStringUTF(env,dcmd_info_array[i].impact),
+ jname, jdesc, jimpact,
dcmd_info_array[i].permission_class==NULL?NULL:(*env)->NewStringUTF(env,dcmd_info_array[i].permission_class),
dcmd_info_array[i].permission_name==NULL?NULL:(*env)->NewStringUTF(env,dcmd_info_array[i].permission_name),
dcmd_info_array[i].permission_action==NULL?NULL:(*env)->NewStringUTF(env,dcmd_info_array[i].permission_action),
@@ -175,10 +201,11 @@ Java_com_sun_management_internal_DiagnosticCommandImpl_getDiagnosticCommandInfo
args);
if (obj == NULL) {
free(dcmd_info_array);
- JNU_ThrowOutOfMemoryError(env, 0);
return NULL;
}
+
(*env)->SetObjectArrayElement(env, result, i, obj);
+ EXCEPTION_CHECK_AND_FREE(dcmd_info_array);
}
free(dcmd_info_array);
return result;
diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt
index f2e96cacf20..1381a31dc9c 100644
--- a/jdk/test/ProblemList.txt
+++ b/jdk/test/ProblemList.txt
@@ -275,8 +275,6 @@ com/sun/jdi/sde/SourceDebugExtensionTest.java 8158066 windows-
java/util/spi/ResourceBundleControlProvider/UserDefaultControlTest.java 8062512 generic-all
-java/util/Arrays/ParallelPrefix.java 8080165,8085982 generic-all
-
java/util/BitSet/BitSetStreamTest.java 8079538 generic-all
############################################################################
diff --git a/jdk/test/com/sun/jdi/InvokeHangTest.java b/jdk/test/com/sun/jdi/InvokeHangTest.java
index e6a49eccdba..56ccbc23677 100644
--- a/jdk/test/com/sun/jdi/InvokeHangTest.java
+++ b/jdk/test/com/sun/jdi/InvokeHangTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
* @author jjh
*
* @modules jdk.jdi
+ * @library /test/lib
* @run build TestScaffold VMConnection TargetListener TargetAdapter
* @run compile -g InvokeHangTest.java
* @run driver InvokeHangTest
@@ -133,7 +134,7 @@ public class InvokeHangTest extends TestScaffold {
BreakpointRequest request2;
static volatile int bkpts = 0;
Thread timerThread;
- static int waitTime = 20000;
+ static long waitTime = jdk.test.lib.Utils.adjustTimeout(20000);
InvokeHangTest (String args[]) {
super(args);
diff --git a/jdk/test/com/sun/jdi/OomDebugTest.java b/jdk/test/com/sun/jdi/OomDebugTest.java
new file mode 100644
index 00000000000..144691accc9
--- /dev/null
+++ b/jdk/test/com/sun/jdi/OomDebugTest.java
@@ -0,0 +1,416 @@
+/*
+ * Copyright (c) 2016 Red Hat Inc.
+ *
+ * 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 8153711
+ * @summary JDWP: Memory Leak (global references not deleted after invokeMethod).
+ *
+ * @author Severin Gehwolf
+ *
+ * @library ..
+ * @run build TestScaffold VMConnection TargetListener TargetAdapter
+ * @run compile -g OomDebugTest.java
+ * @run main OomDebugTest OomDebugTestTarget test1
+ * @run main OomDebugTest OomDebugTestTarget test2
+ * @run main OomDebugTest OomDebugTestTarget test3
+ * @run main OomDebugTest OomDebugTestTarget test4
+ * @run main OomDebugTest OomDebugTestTarget test5
+ */
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+import com.sun.jdi.ArrayReference;
+import com.sun.jdi.ArrayType;
+import com.sun.jdi.ClassType;
+import com.sun.jdi.Field;
+import com.sun.jdi.InvocationException;
+import com.sun.jdi.Method;
+import com.sun.jdi.ObjectReference;
+import com.sun.jdi.ReferenceType;
+import com.sun.jdi.StackFrame;
+import com.sun.jdi.VMOutOfMemoryException;
+import com.sun.jdi.Value;
+import com.sun.jdi.event.BreakpointEvent;
+import com.sun.jdi.event.ExceptionEvent;
+
+/***************** Target program **********************/
+
+class OomDebugTestTarget {
+
+ OomDebugTestTarget() {
+ System.out.println("DEBUG: invoked constructor");
+ }
+ static class FooCls {
+ @SuppressWarnings("unused")
+ private byte[] bytes = new byte[3000000];
+ };
+
+ FooCls fooCls = new FooCls();
+ byte[] byteArray = new byte[0];
+
+ void testMethod(FooCls foo) {
+ System.out.println("DEBUG: invoked 'void testMethod(FooCls)', foo == " + foo);
+ }
+
+ void testPrimitive(byte[] foo) {
+ System.out.println("DEBUG: invoked 'void testPrimitive(byte[])', foo == " + foo);
+ }
+
+ byte[] testPrimitiveArrRetval() {
+ System.out.println("DEBUG: invoked 'byte[] testPrimitiveArrRetval()'");
+ return new byte[3000000];
+ }
+
+ FooCls testFooClsRetval() {
+ System.out.println("DEBUG: invoked 'FooCls testFooClsRetval()'");
+ return new FooCls();
+ }
+
+ public void entry() {}
+
+ public static void main(String[] args){
+ System.out.println("DEBUG: OomDebugTestTarget.main");
+ new OomDebugTestTarget().entry();
+ }
+}
+
+/***************** Test program ************************/
+
+public class OomDebugTest extends TestScaffold {
+
+ private static final String[] ALL_TESTS = new String[] {
+ "test1", "test2", "test3", "test4", "test5"
+ };
+ private static final Set ALL_TESTS_SET = new HashSet();
+ static {
+ ALL_TESTS_SET.addAll(Arrays.asList(ALL_TESTS));
+ }
+ private static final String TEST_CLASSES = System.getProperty("test.classes", ".");
+ private static final File RESULT_FILE = new File(TEST_CLASSES, "results.properties");
+ private static final String LAST_TEST = ALL_TESTS[ALL_TESTS.length - 1];
+ private ReferenceType targetClass;
+ private ObjectReference thisObject;
+ private int failedTests;
+ private final String testMethod;
+
+ public OomDebugTest(String[] args) {
+ super(args);
+ if (args.length != 2) {
+ throw new RuntimeException("Test failed unexpectedly.");
+ }
+ this.testMethod = args[1];
+ }
+
+ @Override
+ protected void runTests() throws Exception {
+ try {
+ addListener(new TargetAdapter() {
+
+ @Override
+ public void exceptionThrown(ExceptionEvent event) {
+ String name = event.exception().referenceType().name();
+ System.err.println("DEBUG: Exception thrown in debuggee was: " + name);
+ }
+ });
+ /*
+ * Get to the top of entry()
+ * to determine targetClass and mainThread
+ */
+ BreakpointEvent bpe = startTo("OomDebugTestTarget", "entry", "()V");
+ targetClass = bpe.location().declaringType();
+
+ mainThread = bpe.thread();
+
+ StackFrame frame = mainThread.frame(0);
+ thisObject = frame.thisObject();
+ java.lang.reflect.Method m = findTestMethod();
+ m.invoke(this);
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ failure();
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ failure();
+ }
+ /*
+ * resume the target, listening for events
+ */
+ listenUntilVMDisconnect();
+ }
+
+ private java.lang.reflect.Method findTestMethod()
+ throws NoSuchMethodException, SecurityException {
+ return OomDebugTest.class.getDeclaredMethod(testMethod);
+ }
+
+ private void failure() {
+ failedTests++;
+ }
+
+ /*
+ * Test case: Object reference as method parameter.
+ */
+ @SuppressWarnings("unused") // called via reflection
+ private void test1() throws Exception {
+ System.out.println("DEBUG: ------------> Running test1");
+ try {
+ Field field = targetClass.fieldByName("fooCls");
+ ClassType clsType = (ClassType)field.type();
+ Method constructor = getConstructorForClass(clsType);
+ for (int i = 0; i < 15; i++) {
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ ObjectReference objRef = clsType.newInstance(mainThread,
+ constructor,
+ new ArrayList(0),
+ ObjectReference.INVOKE_NONVIRTUAL);
+ if (objRef.isCollected()) {
+ System.out.println("DEBUG: Object got GC'ed before we can use it. NO-OP.");
+ continue;
+ }
+ invoke("testMethod", "(LOomDebugTestTarget$FooCls;)V", objRef);
+ }
+ } catch (InvocationException e) {
+ handleFailure(e);
+ }
+ }
+
+ /*
+ * Test case: Array reference as method parameter.
+ */
+ @SuppressWarnings("unused") // called via reflection
+ private void test2() throws Exception {
+ System.out.println("DEBUG: ------------> Running test2");
+ try {
+ Field field = targetClass.fieldByName("byteArray");
+ ArrayType arrType = (ArrayType)field.type();
+
+ for (int i = 0; i < 15; i++) {
+ ArrayReference byteArrayVal = arrType.newInstance(3000000);
+ if (byteArrayVal.isCollected()) {
+ System.out.println("DEBUG: Object got GC'ed before we can use it. NO-OP.");
+ continue;
+ }
+ invoke("testPrimitive", "([B)V", byteArrayVal);
+ }
+ } catch (VMOutOfMemoryException e) {
+ defaultHandleOOMFailure(e);
+ }
+ }
+
+ /*
+ * Test case: Array reference as return value.
+ */
+ @SuppressWarnings("unused") // called via reflection
+ private void test3() throws Exception {
+ System.out.println("DEBUG: ------------> Running test3");
+ try {
+ for (int i = 0; i < 15; i++) {
+ invoke("testPrimitiveArrRetval",
+ "()[B",
+ Collections.EMPTY_LIST,
+ vm().mirrorOfVoid());
+ }
+ } catch (InvocationException e) {
+ handleFailure(e);
+ }
+ }
+
+ /*
+ * Test case: Object reference as return value.
+ */
+ @SuppressWarnings("unused") // called via reflection
+ private void test4() throws Exception {
+ System.out.println("DEBUG: ------------> Running test4");
+ try {
+ for (int i = 0; i < 15; i++) {
+ invoke("testFooClsRetval",
+ "()LOomDebugTestTarget$FooCls;",
+ Collections.EMPTY_LIST,
+ vm().mirrorOfVoid());
+ }
+ } catch (InvocationException e) {
+ handleFailure(e);
+ }
+ }
+
+ /*
+ * Test case: Constructor
+ */
+ @SuppressWarnings({ "unused", "unchecked", "rawtypes" }) // called via reflection
+ private void test5() throws Exception {
+ System.out.println("DEBUG: ------------> Running test5");
+ try {
+ ClassType type = (ClassType)thisObject.type();
+ for (int i = 0; i < 15; i++) {
+ type.newInstance(mainThread,
+ findMethod(targetClass, "", "()V"),
+ new ArrayList(0),
+ ObjectReference.INVOKE_NONVIRTUAL);
+ }
+ } catch (InvocationException e) {
+ handleFailure(e);
+ }
+ }
+
+ private Method getConstructorForClass(ClassType clsType) {
+ List methods = clsType.methodsByName("");
+ if (methods.size() != 1) {
+ throw new RuntimeException("FAIL. Expected only one, the default, constructor");
+ }
+ return methods.get(0);
+ }
+
+ private void handleFailure(InvocationException e) {
+ // There is no good way to see the OOME diagnostic message in the target since the
+ // TestScaffold might throw an exception while trying to print the stack trace. I.e
+ // it might get a a VMDisconnectedException before the stack trace printing finishes.
+ System.err.println("FAILURE: InvocationException thrown. Trying to determine cause...");
+ defaultHandleOOMFailure(e);
+ }
+
+ private void defaultHandleOOMFailure(Exception e) {
+ e.printStackTrace();
+ failure();
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ void invoke(String methodName, String methodSig, Value value)
+ throws Exception {
+ List args = new ArrayList(1);
+ args.add(value);
+ invoke(methodName, methodSig, args, value);
+ }
+
+ void invoke(String methodName,
+ String methodSig,
+ @SuppressWarnings("rawtypes") List args,
+ Value value) throws Exception {
+ Method method = findMethod(targetClass, methodName, methodSig);
+ if ( method == null) {
+ failure("FAILED: Can't find method: "
+ + methodName + " for class = " + targetClass);
+ return;
+ }
+ invoke(method, args, value);
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ void invoke(Method method, List args, Value value) throws Exception {
+ thisObject.invokeMethod(mainThread, method, args, 0);
+ System.out.println("DEBUG: Done invoking method via debugger.");
+ }
+
+ Value fieldValue(String fieldName) {
+ Field field = targetClass.fieldByName(fieldName);
+ return thisObject.getValue(field);
+ }
+
+ // Determine the pass/fail status on some heuristic and don't fail the
+ // test if < 3 of the total number of tests (currently 5) fail. This also
+ // has the nice side effect that all tests are first attempted and only
+ // all tests ran an overall pass/fail status is determined.
+ private static void determineOverallTestStatus(OomDebugTest oomTest)
+ throws IOException, FileNotFoundException {
+ Properties resultProps = new Properties();
+ if (!RESULT_FILE.exists()) {
+ RESULT_FILE.createNewFile();
+ }
+ FileInputStream fin = null;
+ try {
+ fin = new FileInputStream(RESULT_FILE);
+ resultProps.load(fin);
+ resultProps.put(oomTest.testMethod,
+ Integer.toString(oomTest.failedTests));
+ } finally {
+ if (fin != null) {
+ fin.close();
+ }
+ }
+ System.out.println("DEBUG: Finished running test '"
+ + oomTest.testMethod + "'.");
+ if (LAST_TEST.equals(oomTest.testMethod)) {
+ System.out.println("DEBUG: Determining overall test status.");
+ Set actualTestsRun = new HashSet();
+ int totalTests = ALL_TESTS.length;
+ int failedTests = 0;
+ for (Object key: resultProps.keySet()) {
+ actualTestsRun.add((String)key);
+ Object propVal = resultProps.get(key);
+ int value = Integer.parseInt((String)propVal);
+ failedTests += value;
+ }
+ if (!ALL_TESTS_SET.equals(actualTestsRun)) {
+ String errorMsg = "Test failed! Expected to run tests '"
+ + ALL_TESTS_SET + "', but only these were run '"
+ + actualTestsRun + "'";
+ throw new RuntimeException(errorMsg);
+ }
+ if (failedTests >= 3) {
+ String errorMsg = "Test failed. Expected < 3 sub-tests to fail "
+ + "for a pass. Got " + failedTests
+ + " failed tests out of " + totalTests + ".";
+ throw new RuntimeException(errorMsg);
+ }
+ RESULT_FILE.delete();
+ System.out.println("All " + totalTests + " tests passed.");
+ } else {
+ System.out.println("DEBUG: More tests to run. Coninuing.");
+ FileOutputStream fout = null;
+ try {
+ fout = new FileOutputStream(RESULT_FILE);
+ resultProps.store(fout, "Storing results after test "
+ + oomTest.testMethod);
+ } finally {
+ if (fout != null) {
+ fout.close();
+ }
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.setProperty("test.vm.opts", "-Xmx40m"); // Set debuggee VM option
+ OomDebugTest oomTest = new OomDebugTest(args);
+ try {
+ oomTest.startTests();
+ } catch (Throwable e) {
+ System.out.println("DEBUG: Got exception for test run. " + e);
+ e.printStackTrace();
+ oomTest.failure();
+ }
+ determineOverallTestStatus(oomTest);
+ }
+
+}
diff --git a/jdk/test/com/sun/net/httpserver/Test5.java b/jdk/test/com/sun/net/httpserver/Test5.java
index b6d39439b7a..f704cf8ef42 100644
--- a/jdk/test/com/sun/net/httpserver/Test5.java
+++ b/jdk/test/com/sun/net/httpserver/Test5.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -145,6 +145,7 @@ public class Test5 extends Test {
socket.close();
s = new String (b,0,count, "ISO8859_1");
if (!compare (s, result)) {
+ System.err.println(" Expected [" + result + "]\n actual [" + s + "]");
throw new RuntimeException ("wrong string result");
}
}
diff --git a/jdk/test/java/beans/XMLEncoder/EnumPrivate.java b/jdk/test/java/beans/XMLEncoder/EnumPrivate.java
deleted file mode 100644
index 05c56007d65..00000000000
--- a/jdk/test/java/beans/XMLEncoder/EnumPrivate.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2007, 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.
- */
-
-enum EnumPrivate {
- A0,B0,C0,D0,E0,F0,G0,H0,I0,J0,K0,L0,M0,N0,O0,P0,Q0,R0,S0,T0,U0,V0,W0,X0,Y0,Z0,
- A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,
- A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2,M2,N2,O2,P2,Q2,R2,S2,T2,U2,V2,W2,X2,Y2,Z2,
- A3,B3,C3,D3,E3,F3,G3,H3,I3,J3,K3,L3,M3,N3,O3,P3,Q3,R3,S3,T3,U3,V3,W3,X3,Y3,Z3,
- A4,B4,C4,D4,E4,F4,G4,H4,I4,J4,K4,L4,M4,N4,O4,P4,Q4,R4,S4,T4,U4,V4,W4,X4,Y4,Z4,
- A5,B5,C5,D5,E5,F5,G5,H5,I5,J5,K5,L5,M5,N5,O5,P5,Q5,R5,S5,T5,U5,V5,W5,X5,Y5,Z5,
- A6,B6,C6,D6,E6,F6,G6,H6,I6,J6,K6,L6,M6,N6,O6,P6,Q6,R6,S6,T6,U6,V6,W6,X6,Y6,Z6,
- A7,B7,C7,D7,E7,F7,G7,H7,I7,J7,K7,L7,M7,N7,O7,P7,Q7,R7,S7,T7,U7,V7,W7,X7,Y7,Z7,
- A8,B8,C8,D8,E8,F8,G8,H8,I8,J8,K8,L8,M8,N8,O8,P8,Q8,R8,S8,T8,U8,V8,W8,X8,Y8,Z8,
- A9,B9,C9,D9,E9,F9,G9,H9,I9,J9,K9,L9,M9,N9,O9,P9,Q9,R9,S9,T9,U9,V9,W9,X9,Y9,Z9,
-}
diff --git a/jdk/test/java/beans/XMLEncoder/java_util_Collections_CheckedMap.java b/jdk/test/java/beans/XMLEncoder/java_util_Collections_CheckedMap.java
deleted file mode 100644
index eb3e5300589..00000000000
--- a/jdk/test/java/beans/XMLEncoder/java_util_Collections_CheckedMap.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2007, 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 6505888
- * @summary Tests CheckedMap encoding
- * @author Sergey Malenkov
- */
-
-import java.util.Collections;
-import java.util.Map;
-
-public final class java_util_Collections_CheckedMap extends AbstractTest