diff --git a/jdk/make/Setup.gmk b/jdk/make/Setup.gmk index d2e706f6a1b..8a81f2b868b 100644 --- a/jdk/make/Setup.gmk +++ b/jdk/make/Setup.gmk @@ -27,7 +27,7 @@ DISABLE_WARNINGS := -Xlint:all,-deprecation,-unchecked,-rawtypes,-cast,-serial,- # To build with all warnings enabled, do the following: # make JAVAC_WARNINGS="-Xlint:all -Xmaxwarns 10000" -JAVAC_WARNINGS := -Xlint:-unchecked,-deprecation,-overrides,auxiliaryclass,classfile,dep-ann,divzero,empty,try,varargs -Werror +JAVAC_WARNINGS := -Xlint:-unchecked,-deprecation,-overrides,auxiliaryclass,classfile,dep-ann,divzero,empty,overloads,try,varargs -Werror # Any java code executed during a JDK build to build other parts of the JDK must be # executed by the bootstrap JDK (probably with -Xbootclasspath/p: ) and for this diff --git a/jdk/src/share/classes/java/lang/Double.java b/jdk/src/share/classes/java/lang/Double.java index 690ca6a8dc3..9ba150e7156 100644 --- a/jdk/src/share/classes/java/lang/Double.java +++ b/jdk/src/share/classes/java/lang/Double.java @@ -833,14 +833,10 @@ public final class Double extends Number implements Comparable { * @return the bits that represent the floating-point number. */ public static long doubleToLongBits(double value) { - long result = doubleToRawLongBits(value); - // Check for NaN based on values of bit fields, maximum - // exponent and nonzero significand. - if ( ((result & DoubleConsts.EXP_BIT_MASK) == - DoubleConsts.EXP_BIT_MASK) && - (result & DoubleConsts.SIGNIF_BIT_MASK) != 0L) - result = 0x7ff8000000000000L; - return result; + if (!isNaN(value)) { + return doubleToRawLongBits(value); + } + return 0x7ff8000000000000L; } /** diff --git a/jdk/src/share/classes/java/lang/Float.java b/jdk/src/share/classes/java/lang/Float.java index 5cc28f99bff..17d2cd7d206 100644 --- a/jdk/src/share/classes/java/lang/Float.java +++ b/jdk/src/share/classes/java/lang/Float.java @@ -741,14 +741,10 @@ public final class Float extends Number implements Comparable { * @return the bits that represent the floating-point number. */ public static int floatToIntBits(float value) { - int result = floatToRawIntBits(value); - // Check for NaN based on values of bit fields, maximum - // exponent and nonzero significand. - if ( ((result & FloatConsts.EXP_BIT_MASK) == - FloatConsts.EXP_BIT_MASK) && - (result & FloatConsts.SIGNIF_BIT_MASK) != 0) - result = 0x7fc00000; - return result; + if (!isNaN(value)) { + return floatToRawIntBits(value); + } + return 0x7fc00000; } /** diff --git a/jdk/src/share/classes/java/lang/Long.java b/jdk/src/share/classes/java/lang/Long.java index fa43fa4d0b5..f873762e1e7 100644 --- a/jdk/src/share/classes/java/lang/Long.java +++ b/jdk/src/share/classes/java/lang/Long.java @@ -700,21 +700,58 @@ public final class Long extends Number implements Comparable { throw new NumberFormatException("Bad digit at end of " + s); } long result = first * radix + second; - if (compareUnsigned(result, first) < 0) { + + /* + * Test leftmost bits of multiprecision extension of first*radix + * for overflow. The number of bits needed is defined by + * GUARD_BIT = ceil(log2(Character.MAX_RADIX)) + 1 = 7. Then + * int guard = radix*(int)(first >>> (64 - GUARD_BIT)) and + * overflow is tested by splitting guard in the ranges + * guard < 92, 92 <= guard < 128, and 128 <= guard, where + * 92 = 128 - Character.MAX_RADIX. Note that guard cannot take + * on a value which does not include a prime factor in the legal + * radix range. + */ + int guard = radix * (int) (first >>> 57); + if (guard >= 128 || + (result >= 0 && guard >= 128 - Character.MAX_RADIX)) { /* - * The maximum unsigned value, (2^64)-1, takes at - * most one more digit to represent than the - * maximum signed value, (2^63)-1. Therefore, - * parsing (len - 1) digits will be appropriately - * in-range of the signed parsing. In other - * words, if parsing (len -1) digits overflows - * signed parsing, parsing len digits will - * certainly overflow unsigned parsing. + * For purposes of exposition, the programmatic statements + * below should be taken to be multi-precision, i.e., not + * subject to overflow. * - * The compareUnsigned check above catches - * situations where an unsigned overflow occurs - * incorporating the contribution of the final - * digit. + * A) Condition guard >= 128: + * If guard >= 128 then first*radix >= 2^7 * 2^57 = 2^64 + * hence always overflow. + * + * B) Condition guard < 92: + * Define left7 = first >>> 57. + * Given first = (left7 * 2^57) + (first & (2^57 - 1)) then + * result <= (radix*left7)*2^57 + radix*(2^57 - 1) + second. + * Thus if radix*left7 < 92, radix <= 36, and second < 36, + * then result < 92*2^57 + 36*(2^57 - 1) + 36 = 2^64 hence + * never overflow. + * + * C) Condition 92 <= guard < 128: + * first*radix + second >= radix*left7*2^57 + second + * so that first*radix + second >= 92*2^57 + 0 > 2^63 + * + * D) Condition guard < 128: + * radix*first <= (radix*left7) * 2^57 + radix*(2^57 - 1) + * so + * radix*first + second <= (radix*left7) * 2^57 + radix*(2^57 - 1) + 36 + * thus + * radix*first + second < 128 * 2^57 + 36*2^57 - radix + 36 + * whence + * radix*first + second < 2^64 + 2^6*2^57 = 2^64 + 2^63 + * + * E) Conditions C, D, and result >= 0: + * C and D combined imply the mathematical result + * 2^63 < first*radix + second < 2^64 + 2^63. The lower + * bound is therefore negative as a signed long, but the + * upper bound is too small to overflow again after the + * signed long overflows to positive above 2^64 - 1. Hence + * result >= 0 implies overflow given C and D. */ throw new NumberFormatException(String.format("String value %s exceeds " + "range of unsigned long.", s)); diff --git a/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 5a3ee424b1a..6a7929166dd 100644 --- a/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -638,6 +638,12 @@ class InvokerBytecodeGenerator { refKind = REF_invokeVirtual; } + if (member.getDeclaringClass().isInterface() && refKind == REF_invokeVirtual) { + // Methods from Object declared in an interface can be resolved by JVM to invokevirtual kind. + // Need to convert it back to invokeinterface to pass verification and make the invocation works as expected. + refKind = REF_invokeInterface; + } + // push arguments for (int i = 0; i < name.arguments.length; i++) { emitPushArgument(name, i); diff --git a/jdk/src/share/classes/java/util/Arrays.java b/jdk/src/share/classes/java/util/Arrays.java index 268205052a9..09135c99969 100644 --- a/jdk/src/share/classes/java/util/Arrays.java +++ b/jdk/src/share/classes/java/util/Arrays.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -1427,12 +1427,14 @@ public class Arrays { * found to violate the {@link Comparator} contract */ public static void sort(T[] a, Comparator c) { - if (c == null) - c = NaturalOrder.INSTANCE; - if (LegacyMergeSort.userRequested) - legacyMergeSort(a, c); - else - TimSort.sort(a, 0, a.length, c, null, 0, 0); + if (c == null) { + sort(a); + } else { + if (LegacyMergeSort.userRequested) + legacyMergeSort(a, c); + else + TimSort.sort(a, 0, a.length, c, null, 0, 0); + } } /** To be removed in a future release. */ @@ -1498,13 +1500,15 @@ public class Arrays { */ public static void sort(T[] a, int fromIndex, int toIndex, Comparator c) { - if (c == null) - c = NaturalOrder.INSTANCE; - rangeCheck(a.length, fromIndex, toIndex); - if (LegacyMergeSort.userRequested) - legacyMergeSort(a, fromIndex, toIndex, c); - else - TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0); + if (c == null) { + sort(a, fromIndex, toIndex); + } else { + rangeCheck(a.length, fromIndex, toIndex); + if (LegacyMergeSort.userRequested) + legacyMergeSort(a, fromIndex, toIndex, c); + else + TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0); + } } /** To be removed in a future release. */ diff --git a/jdk/src/share/classes/java/util/Collections.java b/jdk/src/share/classes/java/util/Collections.java index 8a20078fabf..c172c95f49b 100644 --- a/jdk/src/share/classes/java/util/Collections.java +++ b/jdk/src/share/classes/java/util/Collections.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -121,34 +121,9 @@ public class Collections { * *

The specified list must be modifiable, but need not be resizable. * - *

Implementation note: This implementation is a stable, adaptive, - * iterative mergesort that requires far fewer than n lg(n) comparisons - * when the input array is partially sorted, while offering the - * performance of a traditional mergesort when the input array is - * randomly ordered. If the input array is nearly sorted, the - * implementation requires approximately n comparisons. Temporary - * storage requirements vary from a small constant for nearly sorted - * input arrays to n/2 object references for randomly ordered input - * arrays. - * - *

The implementation takes equal advantage of ascending and - * descending order in its input array, and can take advantage of - * ascending and descending order in different parts of the same - * input array. It is well-suited to merging two or more sorted arrays: - * simply concatenate the arrays and sort the resulting array. - * - *

The implementation was adapted from Tim Peters's list sort for Python - * ( - * TimSort). It uses techniques from Peter McIlroy's "Optimistic - * Sorting and Information Theoretic Complexity", in Proceedings of the - * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474, - * January 1993. - * - *

This implementation dumps the specified list into an array, sorts - * the array, and iterates over the list resetting each element - * from the corresponding position in the array. This avoids the - * n2 log(n) performance that would result from attempting - * to sort a linked list in place. + * @implNote + * This implementation defers to the {@link List#sort(Comparator)} + * method using the specified list and a {@code null} comparator. * * @param the class of the objects in the list * @param list the list to be sorted. @@ -159,16 +134,11 @@ public class Collections { * @throws IllegalArgumentException (optional) if the implementation * detects that the natural ordering of the list elements is * found to violate the {@link Comparable} contract + * @see List#sort(Comparator) */ @SuppressWarnings("unchecked") public static > void sort(List list) { - Object[] a = list.toArray(); - Arrays.sort(a); - ListIterator i = list.listIterator(); - for (Object e : a) { - i.next(); - i.set((T) e); - } + list.sort(null); } /** @@ -183,34 +153,9 @@ public class Collections { * *

The specified list must be modifiable, but need not be resizable. * - *

Implementation note: This implementation is a stable, adaptive, - * iterative mergesort that requires far fewer than n lg(n) comparisons - * when the input array is partially sorted, while offering the - * performance of a traditional mergesort when the input array is - * randomly ordered. If the input array is nearly sorted, the - * implementation requires approximately n comparisons. Temporary - * storage requirements vary from a small constant for nearly sorted - * input arrays to n/2 object references for randomly ordered input - * arrays. - * - *

The implementation takes equal advantage of ascending and - * descending order in its input array, and can take advantage of - * ascending and descending order in different parts of the same - * input array. It is well-suited to merging two or more sorted arrays: - * simply concatenate the arrays and sort the resulting array. - * - *

The implementation was adapted from Tim Peters's list sort for Python - * ( - * TimSort). It uses techniques from Peter McIlroy's "Optimistic - * Sorting and Information Theoretic Complexity", in Proceedings of the - * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474, - * January 1993. - * - *

This implementation dumps the specified list into an array, sorts - * the array, and iterates over the list resetting each element - * from the corresponding position in the array. This avoids the - * n2 log(n) performance that would result from attempting - * to sort a linked list in place. + * @implNote + * This implementation defers to the {@link List#sort(Comparator)} + * method using the specified list and comparator. * * @param the class of the objects in the list * @param list the list to be sorted. @@ -223,16 +168,11 @@ public class Collections { * list-iterator does not support the {@code set} operation. * @throws IllegalArgumentException (optional) if the comparator is * found to violate the {@link Comparator} contract + * @see List#sort(Comparator) */ @SuppressWarnings({"unchecked", "rawtypes"}) public static void sort(List list, Comparator c) { - Object[] a = list.toArray(); - Arrays.sort(a, (Comparator)c); - ListIterator i = list.listIterator(); - for (Object e : a) { - i.next(); - i.set((T) e); - } + list.sort(c); } @@ -4464,10 +4404,12 @@ public class Collections { *

      *     List<String> s = Collections.emptyList();
      * 
- * Implementation note: Implementations of this method need not - * create a separate List object for each call. Using this - * method is likely to have comparable cost to using the like-named - * field. (Unlike this method, the field does not provide type safety.) + * + * @implNote + * Implementations of this method need not create a separate List + * object for each call. Using this method is likely to have comparable + * cost to using the like-named field. (Unlike this method, the field does + * not provide type safety.) * * @param type of elements, if there were any, in the list * @return an empty immutable list diff --git a/jdk/src/share/classes/java/util/List.java b/jdk/src/share/classes/java/util/List.java index 5cbd044169b..80fe4be9229 100644 --- a/jdk/src/share/classes/java/util/List.java +++ b/jdk/src/share/classes/java/util/List.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -415,11 +415,49 @@ public interface List extends Collection { } /** - * Sorts this list using the supplied {@code Comparator} to compare elements. + * Sorts this list according to the order induced by the specified + * {@link Comparator}. + * + *

All elements in this list must be mutually comparable using the + * specified comparator (that is, {@code c.compare(e1, e2)} must not throw + * a {@code ClassCastException} for any elements {@code e1} and {@code e2} + * in the list). + * + *

If the specified comparator is {@code null} then all elements in this + * list must implement the {@link Comparable} interface and the elements' + * {@linkplain Comparable natural ordering} should be used. + * + *

This list must be modifiable, but need not be resizable. * * @implSpec - * The default implementation is equivalent to, for this {@code list}: - *

Collections.sort(list, c)
+ * The default implementation obtains an array containing all elements in + * this list, sorts the array, and iterates over this list resetting each + * element from the corresponding position in the array. (This avoids the + * n2 log(n) performance that would result from attempting + * to sort a linked list in place.) + * + * @implNote + * This implementation is a stable, adaptive, iterative mergesort that + * requires far fewer than n lg(n) comparisons when the input array is + * partially sorted, while offering the performance of a traditional + * mergesort when the input array is randomly ordered. If the input array + * is nearly sorted, the implementation requires approximately n + * comparisons. Temporary storage requirements vary from a small constant + * for nearly sorted input arrays to n/2 object references for randomly + * ordered input arrays. + * + *

The implementation takes equal advantage of ascending and + * descending order in its input array, and can take advantage of + * ascending and descending order in different parts of the same + * input array. It is well-suited to merging two or more sorted arrays: + * simply concatenate the arrays and sort the resulting array. + * + *

The implementation was adapted from Tim Peters's list sort for Python + * ( + * TimSort). It uses techniques from Peter McIlroy's "Optimistic + * Sorting and Information Theoretic Complexity", in Proceedings of the + * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474, + * January 1993. * * @param c the {@code Comparator} used to compare list elements. * A {@code null} value indicates that the elements' @@ -434,8 +472,15 @@ public interface List extends Collection { * contract * @since 1.8 */ + @SuppressWarnings({"unchecked", "rawtypes"}) default void sort(Comparator c) { - Collections.sort(this, c); + Object[] a = this.toArray(); + Arrays.sort(a, (Comparator) c); + ListIterator i = this.listIterator(); + for (Object e : a) { + i.next(); + i.set((E) e); + } } /** diff --git a/jdk/src/share/classes/java/util/stream/ForEachOps.java b/jdk/src/share/classes/java/util/stream/ForEachOps.java index 2c343fbc3c1..92320933813 100644 --- a/jdk/src/share/classes/java/util/stream/ForEachOps.java +++ b/jdk/src/share/classes/java/util/stream/ForEachOps.java @@ -317,12 +317,55 @@ final class ForEachOps { */ @SuppressWarnings("serial") static final class ForEachOrderedTask extends CountedCompleter { + /* + * Our goal is to ensure that the elements associated with a task are + * processed according to an in-order traversal of the computation tree. + * We use completion counts for representing these dependencies, so that + * a task does not complete until all the tasks preceding it in this + * order complete. We use the "completion map" to associate the next + * task in this order for any left child. We increase the pending count + * of any node on the right side of such a mapping by one to indicate + * its dependency, and when a node on the left side of such a mapping + * completes, it decrements the pending count of its corresponding right + * side. As the computation tree is expanded by splitting, we must + * atomically update the mappings to maintain the invariant that the + * completion map maps left children to the next node in the in-order + * traversal. + * + * Take, for example, the following computation tree of tasks: + * + * a + * / \ + * b c + * / \ / \ + * d e f g + * + * The complete map will contain (not necessarily all at the same time) + * the following associations: + * + * d -> e + * b -> f + * f -> g + * + * Tasks e, f, g will have their pending counts increased by 1. + * + * The following relationships hold: + * + * - completion of d "happens-before" e; + * - completion of d and e "happens-before b; + * - completion of b "happens-before" f; and + * - completion of f "happens-before" g + * + * Thus overall the "happens-before" relationship holds for the + * reporting of elements, covered by tasks d, e, f and g, as specified + * by the forEachOrdered operation. + */ + private final PipelineHelper helper; private Spliterator spliterator; private final long targetSize; private final ConcurrentHashMap, ForEachOrderedTask> completionMap; private final Sink action; - private final Object lock; private final ForEachOrderedTask leftPredecessor; private Node node; @@ -333,9 +376,9 @@ final class ForEachOps { this.helper = helper; this.spliterator = spliterator; this.targetSize = AbstractTask.suggestTargetSize(spliterator.estimateSize()); - this.completionMap = new ConcurrentHashMap<>(); + // Size map to avoid concurrent re-sizes + this.completionMap = new ConcurrentHashMap<>(Math.max(16, AbstractTask.LEAF_TARGET << 1)); this.action = action; - this.lock = new Object(); this.leftPredecessor = null; } @@ -348,7 +391,6 @@ final class ForEachOps { this.targetSize = parent.targetSize; this.completionMap = parent.completionMap; this.action = parent.action; - this.lock = parent.lock; this.leftPredecessor = leftPredecessor; } @@ -367,16 +409,42 @@ final class ForEachOps { new ForEachOrderedTask<>(task, leftSplit, task.leftPredecessor); ForEachOrderedTask rightChild = new ForEachOrderedTask<>(task, rightSplit, leftChild); + + // Fork the parent task + // Completion of the left and right children "happens-before" + // completion of the parent + task.addToPendingCount(1); + // Completion of the left child "happens-before" completion of + // the right child + rightChild.addToPendingCount(1); task.completionMap.put(leftChild, rightChild); - task.addToPendingCount(1); // forking - rightChild.addToPendingCount(1); // right pending on left child + + // If task is not on the left spine if (task.leftPredecessor != null) { - leftChild.addToPendingCount(1); // left pending on previous subtree, except left spine - if (task.completionMap.replace(task.leftPredecessor, task, leftChild)) - task.addToPendingCount(-1); // transfer my "right child" count to my left child - else - leftChild.addToPendingCount(-1); // left child is ready to go when ready + /* + * Completion of left-predecessor, or left subtree, + * "happens-before" completion of left-most leaf node of + * right subtree. + * The left child's pending count needs to be updated before + * it is associated in the completion map, otherwise the + * left child can complete prematurely and violate the + * "happens-before" constraint. + */ + leftChild.addToPendingCount(1); + // Update association of left-predecessor to left-most + // leaf node of right subtree + if (task.completionMap.replace(task.leftPredecessor, task, leftChild)) { + // If replaced, adjust the pending count of the parent + // to complete when its children complete + task.addToPendingCount(-1); + } else { + // Left-predecessor has already completed, parent's + // pending count is adjusted by left-predecessor; + // left child is ready to complete + leftChild.addToPendingCount(-1); + } } + ForEachOrderedTask taskToFork; if (forkRight) { forkRight = false; @@ -391,31 +459,47 @@ final class ForEachOps { } taskToFork.fork(); } - if (task.getPendingCount() == 0) { - task.helper.wrapAndCopyInto(task.action, rightSplit); - } - else { + + /* + * Task's pending count is either 0 or 1. If 1 then the completion + * map will contain a value that is task, and two calls to + * tryComplete are required for completion, one below and one + * triggered by the completion of task's left-predecessor in + * onCompletion. Therefore there is no data race within the if + * block. + */ + if (task.getPendingCount() > 0) { + // Cannot complete just yet so buffer elements into a Node + // for use when completion occurs Node.Builder nb = task.helper.makeNodeBuilder( - task.helper.exactOutputSizeIfKnown(rightSplit), - size -> (T[]) new Object[size]); + task.helper.exactOutputSizeIfKnown(rightSplit), + size -> (T[]) new Object[size]); task.node = task.helper.wrapAndCopyInto(nb, rightSplit).build(); + task.spliterator = null; } task.tryComplete(); } @Override public void onCompletion(CountedCompleter caller) { - spliterator = null; if (node != null) { - // Dump any data from this leaf into the sink - synchronized (lock) { - node.forEach(action); - } + // Dump buffered elements from this leaf into the sink + node.forEach(action); node = null; } - ForEachOrderedTask victim = completionMap.remove(this); - if (victim != null) - victim.tryComplete(); + else if (spliterator != null) { + // Dump elements output from this leaf's pipeline into the sink + helper.wrapAndCopyInto(action, spliterator); + spliterator = null; + } + + // The completion of this task *and* the dumping of elements + // "happens-before" completion of the associated left-most leaf task + // of right subtree (if any, which can be this task's right sibling) + // + ForEachOrderedTask leftDescendant = completionMap.remove(this); + if (leftDescendant != null) + leftDescendant.tryComplete(); } } } diff --git a/jdk/src/share/classes/java/util/stream/StreamSupport.java b/jdk/src/share/classes/java/util/stream/StreamSupport.java index 70af2da5e3b..9a1820cca28 100644 --- a/jdk/src/share/classes/java/util/stream/StreamSupport.java +++ b/jdk/src/share/classes/java/util/stream/StreamSupport.java @@ -54,7 +54,7 @@ public final class StreamSupport { * late-binding. Otherwise, * {@link #stream(java.util.function.Supplier, int, boolean)} should be used * to reduce the scope of potential interference with the source. See - * Non-Interference for + * Non-Interference for * more details. * * @param the type of stream elements @@ -89,7 +89,7 @@ public final class StreamSupport { * source. Since the supplier is only invoked after the terminal operation * commences, any modifications to the source up to the start of the * terminal operation are reflected in the stream result. See - * Non-Interference for + * Non-Interference for * more details. * * @param the type of stream elements @@ -125,7 +125,7 @@ public final class StreamSupport { * late-binding. Otherwise, * {@link #intStream(java.util.function.Supplier, int, boolean)} should be * used to reduce the scope of potential interference with the source. See - * Non-Interference for + * Non-Interference for * more details. * * @param spliterator a {@code Spliterator.OfInt} describing the stream elements @@ -158,7 +158,7 @@ public final class StreamSupport { * source. Since the supplier is only invoked after the terminal operation * commences, any modifications to the source up to the start of the * terminal operation are reflected in the stream result. See - * Non-Interference for + * Non-Interference for * more details. * * @param supplier a {@code Supplier} of a {@code Spliterator.OfInt} @@ -192,7 +192,7 @@ public final class StreamSupport { * late-binding. Otherwise, * {@link #longStream(java.util.function.Supplier, int, boolean)} should be * used to reduce the scope of potential interference with the source. See - * Non-Interference for + * Non-Interference for * more details. * * @param spliterator a {@code Spliterator.OfLong} describing the stream elements @@ -226,7 +226,7 @@ public final class StreamSupport { * source. Since the supplier is only invoked after the terminal operation * commences, any modifications to the source up to the start of the * terminal operation are reflected in the stream result. See - * Non-Interference for + * Non-Interference for * more details. * * @param supplier a {@code Supplier} of a {@code Spliterator.OfLong} @@ -260,7 +260,7 @@ public final class StreamSupport { * late-binding. Otherwise, * {@link #doubleStream(java.util.function.Supplier, int, boolean)} should * be used to reduce the scope of potential interference with the source. See - * Non-Interference for + * Non-Interference for * more details. * * @param spliterator A {@code Spliterator.OfDouble} describing the stream elements @@ -294,7 +294,7 @@ public final class StreamSupport { * source. Since the supplier is only invoked after the terminal operation * commences, any modifications to the source up to the start of the * terminal operation are reflected in the stream result. See - * Non-Interference for + * Non-Interference for * more details. * * @param supplier A {@code Supplier} of a {@code Spliterator.OfDouble} diff --git a/jdk/src/share/classes/java/util/stream/package-info.java b/jdk/src/share/classes/java/util/stream/package-info.java index 810e2fc37f9..016c86dd382 100644 --- a/jdk/src/share/classes/java/util/stream/package-info.java +++ b/jdk/src/share/classes/java/util/stream/package-info.java @@ -206,7 +206,7 @@ * as {@link java.util.function.Function}, and are often lambda expressions or * method references. * - *

Non-interference

+ *

Non-interference

* * Streams enable you to execute possibly-parallel aggregate operations over a * variety of data sources, including even non-thread-safe collections such as @@ -729,7 +729,7 @@ * modifications of the data source prior to commencement of the terminal * operation (provided the behavioral parameters to the stream operations meet * the required criteria for non-interference and statelessness). See - * Non-Interference + * Non-Interference * for more details. * * @since 1.8 diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 5ff793c3e13..c42548ebed3 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -277,3 +277,10 @@ tools/launcher/FXLauncherTest.java linux-all # jdk_util ############################################################################ + +# svc_tools + +# 8031482 +sun/tools/jcmd/TestJcmdSanity.java windows-all + +############################################################################ diff --git a/jdk/test/java/lang/Long/Unsigned.java b/jdk/test/java/lang/Long/Unsigned.java index 2ccbc8d509a..3686457ffe6 100644 --- a/jdk/test/java/lang/Long/Unsigned.java +++ b/jdk/test/java/lang/Long/Unsigned.java @@ -23,7 +23,7 @@ /* * @test - * @bug 4504839 4215269 6322074 + * @bug 4504839 4215269 6322074 8030814 * @summary Basic tests for unsigned operations * @author Joseph D. Darcy */ @@ -310,6 +310,55 @@ public class Unsigned { } } + // test case known at one time to fail + errors += testUnsignedOverflow("1234567890abcdef1", 16, true); + + // largest value with guard = 91 = 13*7; radix = 13 + errors += testUnsignedOverflow("196a78a44c3bba320c", 13, false); + + // smallest value with guard = 92 = 23*2*2; radix = 23 + errors += testUnsignedOverflow("137060c6g1c1dg0", 23, false); + + // guard in [92,98]: no overflow + + // one less than smallest guard value to overflow: guard = 99 = 11*3*3, radix = 33 + errors += testUnsignedOverflow("b1w8p7j5q9r6f", 33, false); + + // smallest guard value to overflow: guard = 99 = 11*3*3, radix = 33 + errors += testUnsignedOverflow("b1w8p7j5q9r6g", 33, true); + + // test overflow of overflow + BigInteger maxUnsignedLong = + BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE); + for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) { + BigInteger quotient = maxUnsignedLong.divide(BigInteger.valueOf(radix)); + for (int addend = 2; addend <= radix; addend++) { + BigInteger b = quotient.multiply(BigInteger.valueOf(radix + addend)); + errors += testUnsignedOverflow(b.toString(radix), radix, b.compareTo(maxUnsignedLong) > 0); + } + } + + return errors; + } + + // test for missing or unexpected unsigned overflow exception + private static int testUnsignedOverflow(String s, int radix, boolean exception) { + int errors = 0; + long result; + try { + result = Long.parseUnsignedLong(s, radix); + if (exception) { + System.err.printf("Unexpected result %d for Long.parseUnsignedLong(%s,%d)\n", + result, s, radix); + errors++; + } + } catch (NumberFormatException nfe) { + if (!exception) { + System.err.printf("Unexpected exception %s for Long.parseUnsignedLong(%s,%d)\n", + nfe.toString(), s, radix); + errors++; + } + } return errors; } diff --git a/jdk/test/java/lang/ProcessBuilder/Basic.java b/jdk/test/java/lang/ProcessBuilder/Basic.java index aa1524a3885..515c6ec18e1 100644 --- a/jdk/test/java/lang/ProcessBuilder/Basic.java +++ b/jdk/test/java/lang/ProcessBuilder/Basic.java @@ -38,6 +38,9 @@ import static java.lang.ProcessBuilder.Redirect.*; import java.io.*; import java.lang.reflect.Field; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import java.util.*; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -524,18 +527,9 @@ public class Basic { } } - private static void copy(String src, String dst) { - system("/bin/cp", "-fp", src, dst); - } - - private static void system(String... command) { - try { - ProcessBuilder pb = new ProcessBuilder(command); - ProcessResults r = run(pb.start()); - equal(r.exitValue(), 0); - equal(r.out(), ""); - equal(r.err(), ""); - } catch (Throwable t) { unexpected(t); } + private static void copy(String src, String dst) throws IOException { + Files.copy(Paths.get(src), Paths.get(dst), + StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES); } private static String javaChildOutput(ProcessBuilder pb, String...args) { @@ -2476,7 +2470,7 @@ public class Basic { static void check(boolean cond, String m) {if (cond) pass(); else fail(m);} static void equal(Object x, Object y) { if (x == null ? y == null : x.equals(y)) pass(); - else fail(x + " not equal to " + y);} + else fail(">'" + x + "'<" + " not equal to " + "'" + y + "'");} public static void main(String[] args) throws Throwable { try {realMain(args);} catch (Throwable t) {unexpected(t);} diff --git a/jdk/test/java/lang/invoke/ObjectMethodInInterfaceTest.java b/jdk/test/java/lang/invoke/ObjectMethodInInterfaceTest.java new file mode 100644 index 00000000000..2ba7116200a --- /dev/null +++ b/jdk/test/java/lang/invoke/ObjectMethodInInterfaceTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, 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 8031502 + * @summary JSR292: IncompatibleClassChangeError in LambdaForm for CharSequence.toString() method handle type converter + * @compile ObjectMethodInInterfaceTest.java + * @run main/othervm -Djava.lang.invoke.MethodHandle.COMPILE_THRESHOLD=0 test.java.lang.invoke.ObjectMethodInInterfaceTest + */ +package test.java.lang.invoke; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +public class ObjectMethodInInterfaceTest { + public static void main(String[] args) throws Throwable { + MethodHandle mh = MethodHandles.lookup().findVirtual(CharSequence.class, "toString", MethodType.methodType(String.class)); + MethodType mt = MethodType.methodType(Object.class, CharSequence.class); + mh = mh.asType(mt); + + Object res = mh.invokeExact((CharSequence)"123"); + + System.out.println("TEST PASSED"); + } +} diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/JcmdBase.java b/jdk/test/lib/testlibrary/jdk/testlibrary/JcmdBase.java index 14599c998bd..f8a212e2bdb 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/JcmdBase.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JcmdBase.java @@ -26,34 +26,91 @@ package jdk.testlibrary; import java.util.Arrays; /** - * Super class for tests which need to attach jcmd to the current process. + * Helper class for starting jcmd process. + *
+ * - jcmd will send diagnostic requests to the current java process:
+ *      jcmd pid_to_current_process PerfCounter.print
+ * - jcmd will be run without sending request to any JVM
+ *      jcmd -h
+ * 
*/ -public class JcmdBase { +public final class JcmdBase { private static ProcessBuilder processBuilder = new ProcessBuilder(); + private JcmdBase() { + // Private constructor to prevent class instantiation + } + /** - * Attach jcmd to the current process + * Sends the diagnostic command request to the current process * - * @param toolArgs - * jcmd command line parameters, e.g. VM.flags - * @return jcmd output + * @see #jcmd(boolean, String[], String[]) + */ + public final static OutputAnalyzer jcmd(String... jcmdArgs) + throws Exception { + return jcmd(true, null, jcmdArgs); + } + + /** + * Sends the diagnostic command request to the current process. + * jcmd will be run with specified {@code vmArgs}. + * + * @see #jcmd(boolean, String[], String[]) + */ + public final static OutputAnalyzer jcmd(String[] vmArgs, + String[] jcmdArgs) throws Exception { + return jcmd(true, vmArgs, jcmdArgs); + } + + /** + * Runs jcmd without sending request to any JVM + * + * @see #jcmd(boolean, String[], String[]) + */ + public final static OutputAnalyzer jcmdNoPid(String[] vmArgs, + String[] jcmdArgs) throws Exception { + return jcmd(false, vmArgs, jcmdArgs); + } + + /** + * If {@code requestToCurrentProcess} is {@code true} + * sends a diagnostic command request to the current process. + * If {@code requestToCurrentProcess} is {@code false} + * runs jcmd without sending request to any JVM. + * + * @param requestToCurrentProcess + * Defines if jcmd will send request to the current process + * @param vmArgs + * jcmd will be run with VM arguments specified, + * e.g. -XX:+UsePerfData + * @param jcmdArgs + * jcmd will be run with option or command and its arguments + * specified, e.g. VM.flags + * @return The output from {@link OutputAnalyzer} object * @throws Exception */ - public final static OutputAnalyzer jcmd(String... toolArgs) - throws Exception { + private static final OutputAnalyzer jcmd(boolean requestToCurrentProcess, + String[] vmArgs, String[] jcmdArgs) throws Exception { JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jcmd"); - launcher.addToolArg(Integer.toString(ProcessTools.getProcessId())); - for (String toolArg : toolArgs) { - launcher.addToolArg(toolArg); + if (vmArgs != null) { + for (String vmArg : vmArgs) { + launcher.addVMArg(vmArg); + } + } + if (requestToCurrentProcess) { + launcher.addToolArg(Integer.toString(ProcessTools.getProcessId())); + } + if (jcmdArgs != null) { + for (String toolArg : jcmdArgs) { + launcher.addToolArg(toolArg); + } } processBuilder.command(launcher.getCommand()); System.out.println(Arrays.toString(processBuilder.command().toArray()).replace(",", "")); OutputAnalyzer output = new OutputAnalyzer(processBuilder.start()); System.out.println(output.getOutput()); - output.shouldHaveExitValue(0); - return output; } diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java b/jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java index d4cbd27fa9b..602df9f0143 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java @@ -23,7 +23,11 @@ package jdk.testlibrary; +import static jdk.testlibrary.Asserts.*; + import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -394,4 +398,99 @@ public final class OutputAnalyzer { public int getExitValue() { return exitValue; } + + /** + * Get the contents of the output buffer (stdout and stderr) as list of strings. + * Output will be split by system property 'line.separator'. + * + * @return Contents of the output buffer as list of strings + */ + public List asLines() { + List l = new ArrayList<>(); + String[] a = getOutput().split(Utils.NEW_LINE); + for (String string : a) { + l.add(string); + } + return l; + } + + /** + * Check if there is a line matching {@code pattern} and return its index + * + * @param pattern Matching pattern + * @return Index of first matching line + */ + private int indexOf(List lines, String pattern) { + for (int i = 0; i < lines.size(); i++) { + if (lines.get(i).matches(pattern)) { + return i; + } + } + return -1; + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public int shouldMatchByLine(String pattern) { + return shouldMatchByLine(null, null, pattern); + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public int shouldMatchByLineFrom(String from, String pattern) { + return shouldMatchByLine(from, null, pattern); + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public int shouldMatchByLineTo(String to, String pattern) { + return shouldMatchByLine(null, to, pattern); + } + + /** + * Verify that the stdout and stderr contents of output buffer match the + * {@code pattern} line by line. The whole output could be matched or + * just a subset of it. + * + * @param from + * The line from where output will be matched. + * Set {@code from} to null for matching from the first line. + * @param to + * The line until where output will be matched. + * Set {@code to} to null for matching until the last line. + * @param pattern + * Matching pattern + * @return Count of lines which match the {@code pattern} + */ + public int shouldMatchByLine(String from, String to, String pattern) { + List lines = asLines(); + + int fromIndex = 0; + if (from != null) { + fromIndex = indexOf(lines, from); + assertGreaterThan(fromIndex, -1, + "The line/pattern '" + from + "' from where the output should match can not be found"); + } + + int toIndex = lines.size(); + if (to != null) { + toIndex = indexOf(lines, to); + assertGreaterThan(toIndex, -1, + "The line/pattern '" + to + "' until where the output should match can not be found"); + } + + List subList = lines.subList(fromIndex, toIndex); + int matchedCount = 0; + for (String line : subList) { + assertTrue(line.matches(pattern), + "The line '" + line + "' does not match pattern '" + pattern + "'"); + matchedCount++; + } + + return matchedCount; + } + } diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java b/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java index d557a7ef439..bc2a019ae86 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java @@ -25,6 +25,9 @@ package jdk.testlibrary; import static jdk.testlibrary.Asserts.assertTrue; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; @@ -56,7 +59,6 @@ public final class Utils { */ public static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "").trim(); - private Utils() { // Private constructor to prevent class instantiation } @@ -203,7 +205,6 @@ public final class Utils { * @throws Exception If multiple matching jvms are found. */ public static int tryFindJvmPid(String key) throws Throwable { - ProcessBuilder pb = null; OutputAnalyzer output = null; try { JDKToolLauncher jcmdLauncher = JDKToolLauncher.create("jcmd"); @@ -229,4 +230,24 @@ public final class Utils { throw t; } } + + /** + * Returns file content as a list of strings + * + * @param file File to operate on + * @return List of strings + * @throws IOException + */ + public static List fileAsList(File file) throws IOException { + assertTrue(file.exists() && file.isFile(), + file.getAbsolutePath() + " does not exist or not a file"); + List output = new ArrayList<>(); + try (BufferedReader reader = new BufferedReader(new FileReader(file.getAbsolutePath()))) { + while (reader.ready()) { + output.add(reader.readLine().replace(NEW_LINE, "")); + } + } + return output; + } + } diff --git a/jdk/test/sun/tools/jcmd/TestJcmdDefaults.java b/jdk/test/sun/tools/jcmd/TestJcmdDefaults.java new file mode 100644 index 00000000000..a5310862859 --- /dev/null +++ b/jdk/test/sun/tools/jcmd/TestJcmdDefaults.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static jdk.testlibrary.Asserts.*; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import jdk.testlibrary.JcmdBase; +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.Utils; + +/** + * Unit test for jcmd utility. Tests jcmd options which do not send + * requests to a specific JVM process. + */ +/* + * @test + * @bug 7104647 + * @library /lib/testlibrary + * @run main TestJcmdDefaults + */ +public class TestJcmdDefaults { + + private static final String TEST_SRC = System.getProperty("test.src").trim(); + private static final String[] VM_ARGS = new String[] { "-XX:+UsePerfData" }; + private static final String JCMD_LIST_REGEX = "^\\d+\\s*.*"; + + public static void main(String[] args) throws Exception { + testJcmdUsage("-h"); + testJcmdUsage("-help"); + testJcmdDefaults(); + testJcmdDefaults("-l"); + } + + /** + * jcmd -J-XX:+UsePerfData -h + * jcmd -J-XX:+UsePerfData -help + */ + private static void testJcmdUsage(String... jcmdArgs) throws Exception { + OutputAnalyzer output = JcmdBase.jcmdNoPid(VM_ARGS, jcmdArgs); + + assertNotEquals(output.getExitValue(), 0); + verifyOutputAgainstFile(output); + } + + /** + * jcmd -J-XX:+UsePerfData + * jcmd -J-XX:+UsePerfData -l + */ + private static void testJcmdDefaults(String... jcmdArgs) throws Exception { + OutputAnalyzer output = JcmdBase.jcmdNoPid(VM_ARGS, jcmdArgs); + + output.shouldHaveExitValue(0); + output.shouldContain("sun.tools.jcmd.JCmd"); + matchListedProcesses(output); + } + + /** + * Verifies the listed processes match a certain pattern. + * + * The output should look like: + * 12246 sun.tools.jcmd.JCmd + * 24428 com.sun.javatest.regtest.MainWrapper /tmp/jtreg/jtreg-workdir/classes/sun/tools/jcmd/TestJcmdDefaults.jta + * + * @param output The generated output from the jcmd. + * @throws Exception + */ + private static void matchListedProcesses(OutputAnalyzer output) throws Exception { + int matchedCount = output.shouldMatchByLine(JCMD_LIST_REGEX); + assertGreaterThan(matchedCount , 0, + "Found no lines matching pattern: " + JCMD_LIST_REGEX); + } + + private static void verifyOutputAgainstFile(OutputAnalyzer output) throws IOException { + File file = new File(TEST_SRC, "usage.out"); + List fileOutput = Utils.fileAsList(file); + List outputAsLines = output.asLines(); + assertTrue(outputAsLines.containsAll(fileOutput), + "The ouput should contain all content of " + file.getAbsolutePath()); + } + +} diff --git a/jdk/test/sun/tools/jcmd/TestJcmdSanity.java b/jdk/test/sun/tools/jcmd/TestJcmdSanity.java new file mode 100644 index 00000000000..52fa840fe43 --- /dev/null +++ b/jdk/test/sun/tools/jcmd/TestJcmdSanity.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static jdk.testlibrary.Asserts.*; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import jdk.testlibrary.JcmdBase; +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.Utils; + +/** + * Unit test for jcmd utility. The test will send different diagnostic command + * requests to the current java process. + */ +/* + * @test + * @bug 7104647 7154822 + * @library /lib/testlibrary + * @run main TestJcmdSanity + */ +public class TestJcmdSanity { + + private static final String TEST_SRC = System.getProperty("test.src").trim(); + private static final String[] VM_ARGS = new String[] { "-XX:+UsePerfData" }; + private static final String JCMD_COMMAND_REGEX = "(\\w|\\.)*"; + private static final String PERF_COUNTER_REGEX = "(\\w|\\.)*\\=.*"; + + public static void main(String[] args) throws Exception { + testJcmdPidHelp(); + testJcmdPidHelpHelp(); + testJcmdPid_f(); + testJcmdPidPerfCounterPrint(); + testJcmdPidBigScript(); + } + + /** + * jcmd -J-XX:+UsePerfData pid help + */ + private static void testJcmdPidHelp() throws Exception { + OutputAnalyzer output = JcmdBase.jcmd(VM_ARGS, + new String[] {"help"}); + + output.shouldHaveExitValue(0); + output.shouldNotContain("Exception"); + output.shouldContain(Integer.toString(ProcessTools.getProcessId()) + ":"); + matchJcmdCommands(output); + output.shouldContain("For more information about a specific command use 'help '."); + } + + /** + * jcmd -J-XX:+UsePerfData pid help help + */ + private static void testJcmdPidHelpHelp() throws Exception { + OutputAnalyzer output = JcmdBase.jcmd(VM_ARGS, + new String[] {"help", "help"}); + + output.shouldHaveExitValue(0); + verifyOutputAgainstFile(output); + } + + /** + * jcmd -J-XX:+UsePerfData pid PerfCounter.print + */ + private static void testJcmdPidPerfCounterPrint() throws Exception { + OutputAnalyzer output = JcmdBase.jcmd(VM_ARGS, + new String[] {"PerfCounter.print"}); + + output.shouldHaveExitValue(0); + matchPerfCounters(output); + } + + /** + * jcmd -J-XX:+UsePerfData pid -f dcmd-script.txt + */ + private static void testJcmdPid_f() throws Exception { + File scrpitFile = new File(TEST_SRC, "dcmd-script.txt"); + OutputAnalyzer output = JcmdBase.jcmd(VM_ARGS, + new String[] {"-f", scrpitFile.getAbsolutePath()}); + + output.shouldHaveExitValue(0); + verifyOutputAgainstFile(output); + } + + /** + * Tests that it possible send a file over 1024 bytes large via jcmd -f. + * + * jcmd -J-XX:+UsePerfData pid -f dcmd-big-script.txt + */ + private static void testJcmdPidBigScript() throws Exception { + File scrpitFile = new File(TEST_SRC, "dcmd-big-script.txt"); + OutputAnalyzer output = JcmdBase.jcmd(VM_ARGS, + new String[] {"-f", scrpitFile.getAbsolutePath()}); + + output.shouldHaveExitValue(0); + output.shouldNotContain("Exception"); + output.shouldContain(System.getProperty("java.vm.name").trim()); + } + + /** + * Verifies the listed jcmd commands match a certain pattern. + * + * The output of the jcmd commands should look like: + * VM.uptime + * VM.flags + * VM.system_properties + * + * @param output The generated output from the jcmd. + * @throws Exception + */ + private static void matchJcmdCommands(OutputAnalyzer output) throws Exception { + int matchedCount = output.shouldMatchByLine(JCMD_COMMAND_REGEX, + "help", + JCMD_COMMAND_REGEX); + assertGreaterThan(matchedCount , 0, + "Found no lines matching pattern: " + JCMD_COMMAND_REGEX); + } + + /** + * Verifies the generated output from the PerfCounter.print command + * matches a certain pattern. + * + * The output of perf counters should look like: + * java.property.java.vm.name="Java HotSpot(TM) 64-Bit Server VM" + * java.threads.daemon=7 + * sun.rt.javaCommand="com.sun.javatest.regtest.MainWrapper /tmp/jtreg/jtreg-workdir/classes/sun/tools/jcmd/TestJcmdSanity.jta" + * + * @param output The generated output from the PerfCounter.print command. + * @throws Exception + */ + private static void matchPerfCounters(OutputAnalyzer output) throws Exception { + int matchedCount = output.shouldMatchByLineFrom(PERF_COUNTER_REGEX, + PERF_COUNTER_REGEX); + assertGreaterThan(matchedCount , 0, + "Found no lines matching pattern: " + PERF_COUNTER_REGEX); + } + + private static void verifyOutputAgainstFile(OutputAnalyzer output) throws IOException { + File file = new File(TEST_SRC, "help_help.out"); + List fileOutput = Utils.fileAsList(file); + List outputAsLines = output.asLines(); + assertTrue(outputAsLines.containsAll(fileOutput), + "The ouput should contain all content of " + file.getAbsolutePath()); + } + +} diff --git a/jdk/test/sun/tools/jcmd/help_help.out b/jdk/test/sun/tools/jcmd/help_help.out index beaf0f35b94..3f151b92acd 100644 --- a/jdk/test/sun/tools/jcmd/help_help.out +++ b/jdk/test/sun/tools/jcmd/help_help.out @@ -1,7 +1,7 @@ help For more information about a specific command use 'help '. With no argument this will show a list of available commands. 'help all' will show help for all commands. -Impact: Low +Impact: Low Syntax : help [options] [] diff --git a/jdk/test/sun/tools/jcmd/jcmd-Defaults.sh b/jdk/test/sun/tools/jcmd/jcmd-Defaults.sh deleted file mode 100644 index 2d6aa2ebe89..00000000000 --- a/jdk/test/sun/tools/jcmd/jcmd-Defaults.sh +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# @test -# @bug 7104647 -# @run shell jcmd-Defaults.sh -# @summary Test that output of 'jcmd' and 'jcmd -l' match a specific pattern - -JCMD="${TESTJAVA}/bin/jcmd" - -${JCMD} -J-XX:+UsePerfData 2>&1 | awk -f ${TESTSRC}/jcmd_Output1.awk - -${JCMD} -J-XX:+UsePerfData -l 2>&1 | awk -f ${TESTSRC}/jcmd_Output1.awk diff --git a/jdk/test/sun/tools/jcmd/jcmd-big-script.sh b/jdk/test/sun/tools/jcmd/jcmd-big-script.sh deleted file mode 100644 index a101c8cf2a8..00000000000 --- a/jdk/test/sun/tools/jcmd/jcmd-big-script.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh - -# -# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - - -# @test -# @bug 7154822 -# @summary test if we can send a file over 1024 bytes large via jcmd -f -# @author David Buck -# -# @library ../common -# @build SimpleApplication ShutdownSimpleApplication -# @run shell jcmd-big-script.sh - -. ${TESTSRC}/../common/CommonSetup.sh -. ${TESTSRC}/../common/ApplicationSetup.sh - -# Start application and use PORTFILE for coordination -PORTFILE="${TESTCLASSES}"/shutdown.port -startApplication SimpleApplication "${PORTFILE}" - -failed=0; - -# -f