changeset 7616:f5ce4c3958b1

Merge
author mduigou
date Tue, 12 Mar 2013 17:06:19 -0700
parents fbd0019da331 a89351237ea6
children 1a9739e922cd
files
diffstat 21 files changed, 413 insertions(+), 282 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/lang/invoke/SerializedLambda.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/src/share/classes/java/lang/invoke/SerializedLambda.java	Tue Mar 12 17:06:19 2013 -0700
@@ -25,6 +25,7 @@
 package java.lang.invoke;
 
 import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
--- a/src/share/classes/java/util/Collections.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/src/share/classes/java/util/Collections.java	Tue Mar 12 17:06:19 2013 -0700
@@ -31,6 +31,7 @@
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
+import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.function.UnaryOperator;
 
@@ -2127,12 +2128,38 @@
             synchronized (mutex) {return m.toString();}
         }
 
-        public void forEach(BiConsumer<? super K, ? super V> consumer) {
-            synchronized (mutex) {m.forEach(consumer);}
+        // Default methods
+
+        public void forEach(BiConsumer<? super K, ? super V> action) {
+            synchronized (mutex) {m.forEach(action);}
         }
         public void replaceAll(BiFunction<K, V, V> function) {
             synchronized (mutex) {m.replaceAll(function);}
         }
+        public V putIfAbsent(K key, V value) {
+            synchronized (mutex) {return m.putIfAbsent(key, value);}
+        }
+        public boolean remove(Object key, Object value) {
+            synchronized (mutex) {return m.remove(key, value);}
+        }
+        public boolean replace(K key, V oldValue, V newValue) {
+            synchronized (mutex) {return m.replace(key, oldValue, newValue);}
+        }
+        public V replace(K key, V value) {
+            synchronized (mutex) {return m.replace(key, value);}
+        }
+        public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
+            synchronized (mutex) {return m.computeIfAbsent(key, mappingFunction);}
+        }
+        public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+            synchronized (mutex) {return m.computeIfPresent(key, remappingFunction);}
+        }
+        public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+            synchronized (mutex) {return m.compute(key, remappingFunction);}
+        }
+        public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+            synchronized (mutex) {return m.merge(key, value, remappingFunction);}
+        }
 
         private void writeObject(ObjectOutputStream s) throws IOException {
             synchronized (mutex) {s.defaultWriteObject();}
--- a/src/share/classes/java/util/Map.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/src/share/classes/java/util/Map.java	Tue Mar 12 17:06:19 2013 -0700
@@ -483,25 +483,76 @@
     // Defaultable methods
 
     /**
-     * Execute the specified {@code BiConsumer} with the key and value of
-     * each entry in this map.
+     * Performs the given action on each entry in this map, in the
+     * order entries are returned by an entry set iterator, until all entries
+     * have been processed or the action throws an {@code Exception}.
+     * Exceptions thrown by the action are relayed to the caller.
      *
-     * @param block the {@code BiConsumer} to which entries will be applied
+     * <p>The default implementation should be overridden by implementations if
+     * they can provide a more performant implementation than an iterator-based
+     * one.
+     *
+     * <p>The default implementation makes no guarantees about
+     * synchronization or atomicity properties of this method. Any
+     * class overriding this method must specify its concurrency
+     * properties. In particular, all implementations of
+     * subinterface {@link java.util.concurrent.ConcurrentMap}
+     * must ensure that this operation is performed atomically.
+     *
+     * @implSpec
+     * <p>The default implementation is equivalent to, for this {@code map}:
+     * <pre> {@code
+     *     for ((Map.Entry<K, V> entry : map.entrySet())
+     *         action.accept(entry.getKey(), entry.getValue());
+     * }</pre>
+     *
+     * @param action The action to be performed for each entry
+     * @throws NullPointerException if the specified action is null
+     * @since 1.8
      */
-    default void forEach(BiConsumer<? super K, ? super V> block) {
-        Objects.requireNonNull(block);
+    default void forEach(BiConsumer<? super K, ? super V> action) {
+        Objects.requireNonNull(action);
         for (Map.Entry<K, V> entry : entrySet()) {
-            block.accept(entry.getKey(), entry.getValue());
+            action.accept(entry.getKey(), entry.getValue());
         }
     }
 
     /**
-     * Apply the specified function to each entry in this map, replacing
+     * Apply the specified function to each entry in this map, in the
+     * order entries are returned by an entry set iterator, and replacing
      * each entry's value with the result of calling the function's
      * {@link BiFunction#apply(Object, Object) BiFunction.apply(K key, V, value)}
-     * method with the current entry's key and value.
+     * method with the current entry's key and value.  Exceptions thrown by the
+     * function are relayed to the caller.
+     *
+     * <p>The default implementation makes no guarantees about
+     * synchronization or atomicity properties of this method. Any
+     * class overriding this method must specify its concurrency
+     * properties. In particular, all implementations of
+     * subinterface {@link java.util.concurrent.ConcurrentMap}
+     * must ensure that this operation is performed atomically.
+     *
+     * @implSpec
+     * <p>The default implementation is equivalent to, for this {@code map}:
+     * <pre> {@code
+     *     for ((Map.Entry<K, V> entry : map.entrySet())
+     *         entry.setValue(function.apply(entry.getKey(), entry.getValue()));
+     * }</pre>
      *
      * @param function the function to apply to each entry
+     * @throws UnsupportedOperationException if the <tt>put</tt> operation
+     *         is not supported by this map
+     * @throws ClassCastException if the class of the specified value
+     *         prevents it from being stored in the backing map
+     * @throws NullPointerException if the specified function is null, or the
+     *         specified key or value is null, and this map does not permit null
+     *         keys or values
+     * @throws IllegalArgumentException if some property of the specified key
+     *         or value prevents it from being stored in this map
+     * @throws IllegalStateException implementations may, but are not
+     *         required to, throw this exception if the entry has been
+     *         removed from the backing map.
+     * @since 1.8
      */
     default void replaceAll(BiFunction<K, V, V> function) {
         Objects.requireNonNull(function);
@@ -515,7 +566,15 @@
      * associates it with the given value and returns {@code null},
      * else returns the current value.
      *
-     * <p>The default implementation is equivalent to, for this {@code
+     * <p>The default implementation makes no guarantees about
+     * synchronization or atomicity properties of this method. Any
+     * class overriding this method must specify its concurrency
+     * properties. In particular, all implementations of
+     * subinterface {@link java.util.concurrent.ConcurrentMap}
+     * must ensure that this operation is performed atomically.
+     *
+     * @implSpec
+     * The default implementation is equivalent to, for this {@code
      * map}:
      *
      *  <pre> {@code
@@ -524,13 +583,6 @@
      * else
      *   return map.get(key);}</pre>
      *
-     * <p>The default implementation makes no guarantees about
-     * synchronization or atomicity properties of this method. Any
-     * class overriding this method must specify its concurrency
-     * properties. In particular, all implementations of
-     * subinterface {@link java.util.concurrent.ConcurrentMap}
-     * must ensure that this operation is performed atomically.
-     *
      * @param key key with which the specified value is to be associated
      * @param value value to be associated with the specified key
      * @return the previous value associated with the specified key, or
@@ -546,6 +598,7 @@
      *         and this map does not permit null keys or values
      * @throws IllegalArgumentException if some property of the specified key
      *         or value prevents it from being stored in this map
+     * @since 1.8
      */
     default V putIfAbsent(K key, V value) {
         return containsKey(key) ? get(key) : put(key, value);
@@ -555,15 +608,6 @@
      * Removes the entry for the specified key only if it is currently
      * mapped to the specified value.
      *
-     * <p>The default implementation is equivalent to, for this {@code map}:
-     *
-     *  <pre> {@code
-     * if (map.containsKey(key) && map.get(key).equals(value)) {
-     *   map.remove(key);
-     *   return true;
-     * } else
-     *   return false;}</pre>
-     *
      * <p>The default implementation makes no guarantees about
      * synchronization or atomicity properties of this method. Any
      * class overriding this method must specify its concurrency
@@ -571,6 +615,16 @@
      * subinterface {@link java.util.concurrent.ConcurrentMap}
      * must ensure that this operation is performed atomically.
      *
+     * @implSpec
+     * The default implementation is equivalent to, for this {@code map}:
+     *
+     * <pre> {@code
+     * if (map.containsKey(key) && map.get(key).equals(value)) {
+     *   map.remove(key);
+     *   return true;
+     * } else
+     *   return false;}</pre>
+     *
      * @param key key with which the specified value is associated
      * @param value value expected to be associated with the specified key
      * @return <tt>true</tt> if the value was removed
@@ -582,6 +636,7 @@
      * @throws NullPointerException if the specified key or value is null,
      *         and this map does not permit null keys or values
      *         (<a href="Collection.html#optional-restrictions">optional</a>)
+     * @since 1.8
      */
     default boolean remove(Object key, Object value) {
         if (!containsKey(key) || !get(key).equals(value))
@@ -594,15 +649,6 @@
      * Replaces the entry for the specified key only if currently
      * mapped to the specified value.
      *
-     * <p>The default implementation is equivalent to, for this {@code map}:
-     *
-     *  <pre> {@code
-     * if (map.containsKey(key) && map.get(key).equals(oldValue)) {
-     *   map.put(key, newValue);
-     *   return true;
-     * } else
-     *   return false;}</pre>
-     *
      * <p>The default implementation makes no guarantees about
      * synchronization or atomicity properties of this method. Any
      * class overriding this method must specify its concurrency
@@ -610,6 +656,16 @@
      * subinterface {@link java.util.concurrent.ConcurrentMap}
      * must ensure that this operation is performed atomically.
      *
+     * @implSpec
+     * The default implementation is equivalent to, for this {@code map}:
+     *
+     * <pre> {@code
+     * if (map.containsKey(key) && map.get(key).equals(oldValue)) {
+     *   map.put(key, newValue);
+     *   return true;
+     * } else
+     *   return false;}</pre>
+     *
      * @param key key with which the specified value is associated
      * @param oldValue value expected to be associated with the specified key
      * @param newValue value to be associated with the specified key
@@ -622,6 +678,7 @@
      *         and this map does not permit null keys or values
      * @throws IllegalArgumentException if some property of a specified key
      *         or value prevents it from being stored in this map
+     * @since 1.8
      */
     default boolean replace(K key, V oldValue, V newValue) {
         if (!containsKey(key) || !get(key).equals(oldValue))
@@ -634,14 +691,6 @@
      * Replaces the entry for the specified key only if it is
      * currently mapped to some value.
      *
-     * <p>The default implementation is equivalent to, for this {@code map}:
-     *
-     *  <pre> {@code
-     * if (map.containsKey(key)) {
-     *   return map.put(key, value);
-     * } else
-     *   return null;}</pre>
-     *
      * <p>The default implementation makes no guarantees about
      * synchronization or atomicity properties of this method. Any
      * class overriding this method must specify its concurrency
@@ -649,6 +698,15 @@
      * subinterface {@link java.util.concurrent.ConcurrentMap}
      * must ensure that this operation is performed atomically.
      *
+     * @implSpec
+     * The default implementation is equivalent to, for this {@code map}:
+     *
+     * <pre> {@code
+     * if (map.containsKey(key)) {
+     *   return map.put(key, value);
+     * } else
+     *   return null;}</pre>
+     *
      * @param key key with which the specified value is associated
      * @param value value to be associated with the specified key
      * @return the previous value associated with the specified key, or
@@ -664,6 +722,7 @@
      *         and this map does not permit null keys or values
      * @throws IllegalArgumentException if some property of the specified key
      *         or value prevents it from being stored in this map
+     * @since 1.8
      */
     default V replace(K key, V value) {
         return containsKey(key) ? put(key, value) : null;
@@ -675,24 +734,13 @@
      * the given mapping function and enters it into this map unless
      * {@code null}.
      *
-     * <p>The default implementation is equivalent to the following
-     * steps for this {@code map}, then returning the current value or
-     * {@code null} if now absent:
-     *
-     * <pre> {@code
-     * if (map.get(key) == null) {
-     *   V newValue = mappingFunction.apply(key);
-     *   if (newValue != null)
-     *      map.putIfAbsent(key, newValue);
-     * }}</pre>
-     *
-     * If the function returns {@code null} no mapping is recorded. If
+     * <p>If the function returns {@code null} no mapping is recorded. If
      * the function itself throws an (unchecked) exception, the
      * exception is rethrown, and no mapping is recorded.  The most
      * common usage is to construct a new object serving as an initial
      * mapped value or memoized result, as in:
      *
-     *  <pre> {@code
+     * <pre> {@code
      * map.computeIfAbsent(key, k -> new Value(f(k)));}</pre>
      *
      * <p>The default implementation makes no guarantees about
@@ -706,6 +754,18 @@
      * whether and how this method distinguishes absence from null
      * mappings.
      *
+     * @implSpec
+     * The default implementation is equivalent to the following
+     * steps for this {@code map}, then returning the current value or
+     * {@code null} if now absent:
+     *
+     * <pre> {@code
+     * if (map.get(key) == null) {
+     *   V newValue = mappingFunction.apply(key);
+     *   if (newValue != null)
+     *      map.putIfAbsent(key, newValue);
+     * }}</pre>
+     *
      * @param key key with which the specified value is to be associated
      * @param mappingFunction the function to compute a value
      * @return the current (existing or computed) value associated with
@@ -717,8 +777,7 @@
      *         is not supported by this map
      * @throws ClassCastException if the class of the specified key or value
      *         prevents it from being stored in this map
-     * @throws RuntimeException or Error if the mappingFunction does so,
-     *         in which case the mapping is left unestablished
+     * @since 1.8
      */
     default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
         V v, newValue;
@@ -732,7 +791,24 @@
      * attempts to compute a new mapping given the key and its current
      * mapped value.
      *
-     * <p>The default implementation is equivalent to performing the
+     * <p>If the function returns {@code null}, the mapping is removed (or
+     * remains absent if initially absent).  If the function itself throws an
+     * (unchecked) exception, the exception is rethrown, and the current mapping
+     * is left unchanged.
+     *
+     * <p>The default implementation makes no guarantees about
+     * synchronization or atomicity properties of this method or the
+     * application of the remapping function. Any class overriding
+     * this method must specify its concurrency properties.  In
+     * particular, all implementations of subinterface {@link
+     * java.util.concurrent.ConcurrentMap} must document whether the
+     * function is applied once atomically only if the value is
+     * present.  Any class that permits null values must document
+     * whether and how this method distinguishes absence from null
+     * mappings.
+     *
+     * @implSpec
+     * The default implementation is equivalent to performing the
      * following steps for this {@code map}, then returning the
      * current value or {@code null} if now absent:
      *
@@ -747,22 +823,7 @@
      * }}</pre>
      *
      * In concurrent contexts, the default implementation may retry
-     * these steps when multiple threads attempt updates.  If the
-     * function returns {@code null}, the mapping is removed (or
-     * remains absent if initially absent).  If the function itself
-     * throws an (unchecked) exception, the exception is rethrown, and
-     * the current mapping is left unchanged.
-     *
-     * <p>The default implementation makes no guarantees about
-     * synchronization or atomicity properties of this method or the
-     * application of the remapping function. Any class overriding
-     * this method must specify its concurrency properties.  In
-     * particular, all implementations of subinterface {@link
-     * java.util.concurrent.ConcurrentMap} must document whether the
-     * function is applied once atomically only if the value is
-     * present.  Any class that permits null values must document
-     * whether and how this method distinguishes absence from null
-     * mappings.
+     * these steps when multiple threads attempt updates.
      *
      * @param key key with which the specified value is to be associated
      * @param remappingFunction the function to compute a value
@@ -774,8 +835,7 @@
      *         is not supported by this map
      * @throws ClassCastException if the class of the specified key or value
      *         prevents it from being stored in this map
-     * @throws RuntimeException or Error if the remappingFunction does so,
-     *         in which case the mapping is unchanged
+     * @since 1.8
      */
     default V computeIfPresent(K key,
                                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
@@ -802,7 +862,23 @@
      * map.compute(key, (k, v) -> (v == null) ? msg : v.concat(msg))}</pre>
      * (Method {@link #merge} is often simpler to use for such purposes.)
      *
-     * <p>The default implementation is equivalent to
+     * <p>If the function returns {@code null}, the mapping is removed (or
+     * remains absent if initially absent).  If the function itself throws an
+     * (unchecked) exception, the exception is rethrown, and the current mapping
+     * is left unchanged.
+     *
+     * <p>The default implementation makes no guarantees about
+     * synchronization or atomicity properties of this method or the
+     * application of the remapping function. Any class overriding
+     * this method must specify its concurrency properties.  In
+     * particular, all implementations of subinterface {@link
+     * java.util.concurrent.ConcurrentMap} must document whether the
+     * function is applied exactly once atomically. Any class that
+     * permits null values must document whether and how this method
+     * distinguishes absence from null mappings.
+     *
+     * @implSpec
+     * The default implementation is equivalent to
      * performing the following steps for this {@code map}, then
      * returning the current value or {@code null} if absent:
      *
@@ -816,21 +892,7 @@
      * }</pre>
      *
      * In concurrent contexts, the default implementation may retry
-     * these steps when multiple threads attempt updates.  If the
-     * function returns {@code null}, the mapping is removed (or
-     * remains absent if initially absent).  If the function itself
-     * throws an (unchecked) exception, the exception is rethrown, and
-     * the current mapping is left unchanged.
-     *
-     * <p>The default implementation makes no guarantees about
-     * synchronization or atomicity properties of this method or the
-     * application of the remapping function. Any class overriding
-     * this method must specify its concurrency properties.  In
-     * particular, all implementations of subinterface {@link
-     * java.util.concurrent.ConcurrentMap} must document whether the
-     * function is applied exactly once atomically. Any class that
-     * permits null values must document whether and how this method
-     * distinguishes absence from null mappings.
+     * these steps when multiple threads attempt updates.
      *
      * @param key key with which the specified value is to be associated
      * @param remappingFunction the function to compute a value
@@ -842,8 +904,7 @@
      *         is not supported by this map
      * @throws ClassCastException if the class of the specified key or value
      *         prevents it from being stored in this map
-     * @throws RuntimeException or Error if the remappingFunction does so,
-     *         in which case the mapping is unchanged
+     * @since 1.8
      */
     default V compute(K key,
                       BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
@@ -871,7 +932,23 @@
      * <pre> {@code
      * map.merge(key, msg, String::concat)}</pre>
      *
-     * <p>The default implementation is equivalent to performing the
+     * <p>If the function returns {@code null}, the mapping is removed (or
+     * remains absent if initially absent).  If the function itself throws an
+     * (unchecked) exception, the exception is rethrown, and the current mapping
+     * is left unchanged.
+     *
+     * <p>The default implementation makes no guarantees about
+     * synchronization or atomicity properties of this method or the
+     * application of the remapping function. Any class overriding
+     * this method must specify its concurrency properties.  In
+     * particular, all implementations of subinterface {@link
+     * java.util.concurrent.ConcurrentMap} must document whether the
+     * function is applied exactly once atomically. Any class that
+     * permits null values must document whether and how this method
+     * distinguishes absence from null mappings.
+     *
+     * @implSpec
+     * The default implementation is equivalent to performing the
      * following steps for this {@code map}, then returning the
      * current value or {@code null} if absent:
      *
@@ -888,21 +965,7 @@
      * }</pre>
      *
      * In concurrent contexts, the default implementation may retry
-     * these steps when multiple threads attempt updates.  If the
-     * function returns {@code null}, the mapping is removed (or
-     * remains absent if initially absent).  If the function itself
-     * throws an (unchecked) exception, the exception is rethrown, and
-     * the current mapping is left unchanged.
-     *
-     * <p>The default implementation makes no guarantees about
-     * synchronization or atomicity properties of this method or the
-     * application of the remapping function. Any class overriding
-     * this method must specify its concurrency properties.  In
-     * particular, all implementations of subinterface {@link
-     * java.util.concurrent.ConcurrentMap} must document whether the
-     * function is applied exactly once atomically. Any class that
-     * permits null values must document whether and how this method
-     * distinguishes absence from null mappings.
+     * these steps when multiple threads attempt updates.
      *
      * @param key key with which the specified value is to be associated
      * @param value the value to use if absent
@@ -911,8 +974,7 @@
      * @throws NullPointerException if the specified key is null and
      *         this map does not support null keys, or the
      *         remappingFunction is null
-     * @throws RuntimeException or Error if the remappingFunction does so,
-     *         in which case the mapping is unchanged
+     * @since 1.8
      */
     default V merge(K key, V value,
                     BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
--- a/test-ng/agent/conf/serialize.list	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/agent/conf/serialize.list	Tue Mar 12 17:06:19 2013 -0700
@@ -1,5 +1,6 @@
 #java/util/Optional --- Duplicate class
 #java/util/OptionalDouble --- Duplicate class
+java/lang/invoke/MagicLambdaImpl
 java/util/OptionalInt
 java/util/ArrayList\$SubList
 java/util/function/Function\$\$Lambda.*
@@ -10,13 +11,13 @@
 java/util/stream/StreamTestData\$.*
 java/util/stream/Nodes.*NodeBuilder
 java/util/stream/Nodes\$.*Node
+java/util/stream/AbstractSpinedBuffer
 java/util/stream/SpinedBuffer
 org/openjdk/tests/java/util/stream/OpTestCase\$ExerciseDataStreamBuilder
 org/openjdk/tests/java/util/stream/OpTestCase\$ExerciseDataTerminalBuilder
-org/openjdk/tests/java/util/stream/TabulatorsTest\$GroupedMapAssertion
 org/openjdk/tests/java/util/stream/IntNodeTest
 org/openjdk/tests/java/util/stream/UnorderedStreamTest
 org/openjdk/tests/java/util/stream/GroupByOpTest
-org/openjdk/tests/java/util/stream/TabulatorsTest\$ReduceAssertion
-org/openjdk/tests/java/util/stream/TabulatorsTest\$CollectionAssertion
+org/openjdk/tests/java/util/stream/TabulatorsTest
+org/openjdk/tests/java/util/stream/TabulatorsTest\$.*Assertion
 org/openjdk/tests/java/util/stream/StreamLinkTest
--- a/test-ng/agent/src/com/oracle/lambda/Agent.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/agent/src/com/oracle/lambda/Agent.java	Tue Mar 12 17:06:19 2013 -0700
@@ -31,14 +31,19 @@
 public class Agent {
     public static void premain(String agentArgs, Instrumentation instrumentation)
             throws IOException {
-        final SerializationInjector si = new SerializationInjector(agentArgs);
-        instrumentation.addTransformer(new ClassFileTransformer() {
-            @Override
-            public byte[] transform(final ClassLoader cl, String string,
-                    Class<?> type, ProtectionDomain pd,
-                    byte[] bytes) throws IllegalClassFormatException {
-                return si.transformClass(cl, bytes, false);
-            }
-        });
+        // If run without a config file, all we do is set up the shutdown hook
+        if (agentArgs != null) {
+            final SerializationInjector si = new SerializationInjector(agentArgs);
+            instrumentation.addTransformer(new ClassFileTransformer() {
+                @Override
+                public byte[] transform(final ClassLoader cl, String string,
+                                        Class<?> type, ProtectionDomain pd,
+                                        byte[] bytes) throws IllegalClassFormatException {
+                    return si.transformClass(cl, bytes, false);
+                }
+            });
+        }
+        else
+            TestLambdaSerialization.initializeShutDownHook();
     }
  }
--- a/test-ng/agent/src/com/oracle/lambda/Main.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/agent/src/com/oracle/lambda/Main.java	Tue Mar 12 17:06:19 2013 -0700
@@ -41,6 +41,7 @@
 import java.nio.file.attribute.FileAttribute;
 import java.nio.file.attribute.PosixFilePermission;
 import java.nio.file.attribute.PosixFilePermissions;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -58,35 +59,6 @@
  * @author kumasrin
  */
 public class Main {
-      static void recursiveDelete(File target) throws IOException {
-        if (!target.exists()) {
-            return;
-        }
-        Files.walkFileTree(target.toPath(), new SimpleFileVisitor<Path>() {
-            @Override
-            public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
-                try {
-                    Files.deleteIfExists(dir);
-                } catch (IOException ex) {
-                    System.out.println("Error: could not delete: " + dir.toString());
-                    System.out.println(ex.getMessage());
-                    return FileVisitResult.TERMINATE;
-                }
-                return FileVisitResult.CONTINUE;
-            }
-            @Override
-            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
-                try {
-                    Files.deleteIfExists(file);
-                } catch (IOException ex) {
-                    System.out.println("Error: could not delete: " + file.toString());
-                    System.out.println(ex.getMessage());
-                    return FileVisitResult.TERMINATE;
-                }
-                return FileVisitResult.CONTINUE;
-            }
-        });
-    }
 
     static void usage() {
         System.out.println("usage: -o output_dir -f path_to_list path_to/SomeClass.class");
@@ -108,7 +80,7 @@
         }
         File outDir = null;
         File inFile = null;
-        File listFile = null;
+        File confFile = null;
         String className = null;
         for (int i = 0 ; i < args.length ; i++) {
             switch (args[i]) {
@@ -118,7 +90,7 @@
                     break;
                 case "-f":
                     i++;
-                    listFile = new File(args[i]);
+                    confFile = new File(args[i]);
                     break;
                 case "-c":
                     i++;
@@ -133,7 +105,6 @@
         }
         if (inFile.isDirectory()) {
             if (outDir.exists()) {
-                recursiveDelete(outDir);
                 outDir.mkdirs();
             }
             URL[] urls = {inFile.toURI().toURL()};
@@ -146,13 +117,12 @@
             }
         } else if (inFile.getName().endsWith(".jar")) {
             if (outDir.exists()) {
-                recursiveDelete(outDir);
                 outDir.mkdirs();
             }
             URL[] urls = {inFile.toURI().toURL()};
             ClassLoader cl = new URLClassLoader(urls, ClassLoader.getSystemClassLoader());
             Pattern pattern = Pattern.compile(className != null ? Pattern.quote("className" + ".class") : ".*");
-            doJar(listFile, inFile, outDir, cl, pattern, className != null);
+            doJar(confFile, inFile, outDir, cl, pattern, className != null);
         } else {
             outDir.mkdirs();
             URL[] urls = {inFile.getParentFile().toURI().toURL()};
@@ -175,10 +145,10 @@
         return baos.toByteArray();
     }
 
-    static void doJar(File listFile, File inFile, File outDir, ClassLoader cl, Pattern pattern, boolean forceSerialize) throws IOException {
+    static void doJar(File confFile, File inFile, File outDir, ClassLoader cl, Pattern pattern, boolean forceSerialize) throws IOException {
         JarFile jf = new JarFile(inFile);
         byte[] buffer;
-        SerializationInjector si = new SerializationInjector(listFile);
+        SerializationInjector si = new SerializationInjector(confFile.getAbsolutePath());
         FileSystem fs = null;
         boolean jarOut = outDir.getName().endsWith(".jar");
         Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxrwxrwx");
--- a/test-ng/agent/src/com/oracle/lambda/SerializationInjector.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/agent/src/com/oracle/lambda/SerializationInjector.java	Tue Mar 12 17:06:19 2013 -0700
@@ -28,7 +28,6 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintStream;
-import java.io.PrintWriter;
 import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -38,9 +37,11 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.regex.Pattern;
+
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.ClassVisitor;
 import jdk.internal.org.objectweb.asm.ClassWriter;
@@ -48,55 +49,46 @@
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import static jdk.internal.org.objectweb.asm.Opcodes.*;
 import jdk.internal.org.objectweb.asm.Type;
-import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
+
 import static java.nio.file.StandardOpenOption.*;
 
 public class SerializationInjector {
     static final String PREFIX = "com.oracle.lambda";
-    static final String EXCLUDES = "java.*|javax.*";
+    static final String INCLUDES = "org.openjdk.tests.java.*"; // also should include java.util...
     static final String SERIALIZE = "";
     static PrintStream outputStream;
     static boolean shouldClose = false;
-    final DebugPrint debug;
-    final Pattern excludePattern;
-    final Pattern serializePattern;
     static boolean storeStackTraces;
     static boolean deserializationWorkaround;
+
+    final DebugPrint debug;
+    final Pattern includePattern;
+    final Pattern serializePattern;
     final boolean serializeOnly;
 
     public SerializationInjector() {
-        excludePattern = Pattern.compile(EXCLUDES);
+        includePattern = Pattern.compile(INCLUDES);
         serializePattern = Pattern.compile(SERIALIZE);
         outputStream = System.out;
         debug = new DebugPrint(outputStream, false);
-        initializeShutDownHook();
+        TestLambdaSerialization.initializeShutDownHook();
         storeStackTraces = false;
         deserializationWorkaround = false;
         serializeOnly = false;
     }
-    protected SerializationInjector(File serialize) throws IOException {
-        excludePattern = Pattern.compile(EXCLUDES);
-        serializePattern = fileToPattern(serialize);
-        outputStream = System.out;
-        debug = new DebugPrint(outputStream, true);
-        storeStackTraces = false;
-        deserializationWorkaround = false;
-        serializeOnly = true;
-    }
 
-    public SerializationInjector(String args) throws IOException {
-        final File propsFile = args == null ? null : new File(args);
-        if (propsFile != null) {    
+    public SerializationInjector(String confFile) throws IOException {
+        if (confFile != null) {
             Properties props = new Properties();
-            try (FileInputStream fis = new FileInputStream(args)) {
+            try (FileInputStream fis = new FileInputStream(confFile)) {
                 props.load(fis);
             } catch (IOException ex) {
                 System.err.println("Error: " + ex.getMessage());
                 throw new Error(ex);
             }
             props.list(System.err);
-            String exclude = props.getProperty(PREFIX + ".exclude.files", EXCLUDES);
-            excludePattern = Pattern.compile(exclude);
+            String include = props.getProperty(PREFIX + ".include.files", INCLUDES);
+            includePattern = Pattern.compile(include);
             String injectSerializeName = props.getProperty(PREFIX + ".serialize.file", null);
             storeStackTraces = props.getProperty(PREFIX + ".storeStackTraces", null) != null;
             deserializationWorkaround = props.getProperty(PREFIX +
@@ -110,8 +102,7 @@
                 // if there is no serialization file listed, try to see if there
                 // is one in the agent/conf directory it is usually the same dir
                 // as the props file, othewise use the default patterns.
-                File serializeFile = new File(propsFile.getParentFile(),
-                        "serialize.list");
+                File serializeFile = new File(new File(confFile).getParentFile(), "serialize.list");
                 if (serializeFile.exists()) {
                     System.err.println(serializeFile.getAbsolutePath());
                     serializePattern = fileToPattern(serializeFile);
@@ -141,14 +132,14 @@
             debug = new DebugPrint(outputStream,
             props.getProperty(PREFIX + ".debug") != null);
         } else {
-            excludePattern = Pattern.compile(EXCLUDES);
+            includePattern = Pattern.compile(INCLUDES);
             serializePattern = Pattern.compile(SERIALIZE);
             outputStream = System.out;
             debug = new DebugPrint(outputStream, false);
             storeStackTraces = false;
             deserializationWorkaround = false;
         }
-        initializeShutDownHook();
+        TestLambdaSerialization.initializeShutDownHook();
         serializeOnly = false;
     }
     final Pattern fileToPattern(String filename) throws IOException {
@@ -171,18 +162,6 @@
         return Pattern.compile(regStr);
     }
 
-    final boolean initializeShutDownHook() {
-        Runtime.getRuntime().addShutdownHook(
-            new Thread() {
-                @Override
-                public void run() {
-                    TestLambdaSerialization.printStats();
-                }
-            }
-        );
-        return true;
-    }
-
     byte[] transformClass(ClassLoader cl, byte[] classBuffer, boolean forceSerialize) {
         byte[] xBuffer = classBuffer;
         ClassReader classReader = new ClassReader(xBuffer);
@@ -194,7 +173,7 @@
         if (serializeOnly) {
             return xBuffer;
         }
-        if (excludePattern.matcher(cname).matches()) {
+        if (!includePattern.matcher(cname).matches()) {
             debug.println("Excluding SAND: " + cname);
             return xBuffer;
         }
@@ -209,9 +188,8 @@
                 ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
         classReader.accept(makeSANDVisitor(classWriter, locals), 0);
         byte[] byteArray = classWriter.toByteArray();
-        CheckClassAdapter.verify(new ClassReader(byteArray), cl, false,
-                                 new PrintWriter(System.err));
-
+//        CheckClassAdapter.verify(new ClassReader(byteArray), cl, false,
+//                                 new PrintWriter(System.err));
         return byteArray;
     }
 
@@ -242,13 +220,13 @@
                 };
             }
         }, 0);
+
         return locals;
     }
 
     ClassVisitor makeSANDVisitor(ClassWriter cw, final Map<String, Integer>methodLocals) {
         return new ClassVisitor(V1_8, cw) {
             String cname = null;
-            final Map<String, Integer> mlocals = methodLocals;
             @Override
             public void visit(int version, int access, String name,
                               String signature, String superName,
@@ -266,7 +244,7 @@
                 return new MethodVisitor(V1_8,
                         super.visitMethod(access, name, desc, signature, exceptions)) {
                     final String mid = cname + "+" + name + "+" + desc + "+" + signature;
-                    int locals = mlocals.get(mid);
+                    int locals = methodLocals.containsKey(mid) ? methodLocals.get(mid) : 0;
 
                     int saveArgs(Type[] types) {
                         final int n = locals + 1;
@@ -368,17 +346,33 @@
         ClassReader classReader = new ClassReader(classBuffer);
         ClassWriter classWriter = new ClassWriter(classReader,
                 ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
-        classReader.accept(makeSerializationVisitor(classWriter), 0);
+        boolean hasNoArgCtor = hasNoArgCtor(classBuffer);
+        classReader.accept(makeSerializationVisitor(classWriter, !hasNoArgCtor), 0);
         byte[] byteArray = classWriter.toByteArray();
-        CheckClassAdapter.verify(new ClassReader(byteArray), cl, false,
-                new PrintWriter(System.err));
+        // Needed to comment this out because some classes are actually loaded during this verification
+        // and they fail the package name test (java.*)
+//        CheckClassAdapter.verify(new ClassReader(byteArray), cl, false,
+//                new PrintWriter(System.err));
 
 //        dumpClass(classBuffer, "pre-serialization");
 //        dumpClass(byteArray, "post-serialization");
         return byteArray;
     }
 
-    ClassVisitor makeSerializationVisitor(final ClassWriter cw) {
+    private boolean hasNoArgCtor(byte[] buffer) {
+        final AtomicBoolean foundNoArg = new AtomicBoolean();
+        new ClassReader(buffer).accept(new ClassVisitor(V1_8, null) {
+            @Override
+            public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
+                if (name.equals("<init>") && desc.equals("()V"))
+                    foundNoArg.set(true);
+                return super.visitMethod(access, name, desc, signature, exceptions);
+            }
+        }, 0);
+        return foundNoArg.get();
+    }
+
+    ClassVisitor makeSerializationVisitor(final ClassWriter cw, final boolean injectNoArg) {
         return new ClassVisitor(V1_8, cw) {
             @Override
             public void visit(int version, int access, String name,
@@ -397,6 +391,15 @@
                         signature += "L" + sername + ";";
                 }
                 super.visit(version, access, name, signature, superName, interfaces);
+                if (injectNoArg && (access & ACC_INTERFACE) == 0) {
+                    MethodVisitor ctor = visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+                    ctor.visitCode();
+                    ctor.visitVarInsn(ALOAD, 0);
+                    ctor.visitMethodInsn(INVOKESPECIAL, superName, "<init>", "()V");
+                    ctor.visitInsn(RETURN);
+                    ctor.visitMaxs(-1, -1);
+                    ctor.visitEnd();
+                }
             }
         };
     }
--- a/test-ng/agent/src/com/oracle/lambda/TestLambdaSerialization.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/agent/src/com/oracle/lambda/TestLambdaSerialization.java	Tue Mar 12 17:06:19 2013 -0700
@@ -34,6 +34,7 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
 public class TestLambdaSerialization {
@@ -49,6 +50,8 @@
 
     public static void printStats() {
         PrintStream rpt = SerializationInjector.outputStream;
+        if (rpt == null)
+            rpt = System.out;
         try {
             rpt.println("Lambda Serialization Test Status:");
             rpt.println("  serializations attempted:       " + serCounters.attempted);
@@ -195,6 +198,24 @@
         serializeAndDeserialize(s, "Hi", array);
         serializeAndDeserialize(s, "Bye", array);
     }
+
+    static AtomicBoolean initialized = new AtomicBoolean();
+    static {
+        initializeShutDownHook();
+    }
+
+    static void initializeShutDownHook() {
+        if (initialized.compareAndSet(false, true)) {
+            Runtime.getRuntime().addShutdownHook(
+                    new Thread() {
+                        @Override
+                        public void run() {
+                            printStats();
+                        }
+                    }
+            );
+        }
+    }
 }
 
 class CounterSet {
--- a/test-ng/build.xml	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/build.xml	Tue Mar 12 17:06:19 2013 -0700
@@ -29,7 +29,8 @@
 
     <property name="build.dir" value="../../build/test-ng" />
     <property name="tests.classes.dir" value="${build.dir}/test-classes"/>
-    <property name="mangled.dir" value="${build.dir}/mangled-classes"/>
+    <property name="mangled.bootdir" value="${build.dir}/mangled-bootclasses"/>
+    <property name="mangled.testdir" value="${build.dir}/mangled-testclasses"/>
     <property name="boottests.classes.dir" value="${build.dir}/boottest-classes"/>
     <property name="bootlib.classes.dir" value="${build.dir}/test-bootlib"/>
     <property name="test.reports.dir" value="${build.dir}/test-reports"/>
@@ -43,8 +44,7 @@
     <property name="agent.dir"       location="${basedir}/agent"/>
     <property name="agent.jar"       value="${agent.dir}/dist/SerializationInjectorAgent.jar" />
     <property name="agent.conf.file" value="${agent.dir}/conf/agent.props" />
-    <property name="agent.ser.file"  value="${agent.dir}/conf/serialize.list" />
-    <property name="agent.rt.jar"    value="${java.home}/lib/rt.jar" />
+    <property name="agent.rt.jar"    value="rt.jar" />
 
     <property name="lib.testng.jar" value="${lib.dir}/testng.jar"/>
     <property name="lib.tools.jar" value="${java.home}/../lib/tools.jar"/>
@@ -62,11 +62,17 @@
         <pathelement location="${lib.tools.jar}"/>
     </path>
 
+    <path id="mangled.class.path">
+        <pathelement location="${mangled.testdir}" />
+        <pathelement location="${lib.testng.jar}"/>
+        <pathelement location="${lib.tools.jar}"/>
+    </path>
+
     <taskdef name="testng" classpathref="test.class.path" classname="org.testng.TestNGAntTask" />
 
     <target name="prepare">
         <mkdir dir="${build.dir}"/>
-        <mkdir dir="${mangled.dir}"/>
+        <mkdir dir="${mangled.bootdir}"/>
         <mkdir dir="${tests.classes.dir}"/>
         <mkdir dir="${boottests.classes.dir}"/>
         <mkdir dir="${bootlib.classes.dir}"/>
@@ -138,63 +144,84 @@
         </ant>
     </target>
 
-    <target name="mangle-jdk" depends="build-mangler">
+    <target name="premangle" depends="build-mangler, test-compile">
+        <delete dir="${mangled.bootdir}" />
+        <mkdir dir="${mangled.bootdir}" />
+        <delete dir="${mangled.testdir}" />
+        <mkdir dir="${mangled.testdir}" />
+        <!-- Mangle JDK to mangled.bootdir -->
         <java jar="${agent.jar}" fork="true" >
             <arg value="-o"/>
-            <arg value="${mangled.dir}" />
+            <arg value="${mangled.bootdir}" />
             <arg value="-f"/>
-            <arg value="${agent.ser.file}"/>
+            <arg value="${agent.conf.file}"/>
             <arg value="${agent.rt.jar}"/>
         </java>
+        <!-- Mangle boot test classes to mangled.bootdir -->
+        <jar destfile="${build.dir}/tmpA.jar" basedir="${boottests.classes.dir}"/>
+        <java jar="${agent.jar}" fork="true" >
+            <arg value="-o"/>
+            <arg value="${mangled.bootdir}" />
+            <arg value="-f"/>
+            <arg value="${agent.conf.file}"/>
+            <arg value="${build.dir}/tmpA.jar"/>
+        </java>
+        <!-- Mangle boot lib classes to mangled.bootdir -->
+        <jar destfile="${build.dir}/tmpB.jar" basedir="${bootlib.classes.dir}"/>
+        <java jar="${agent.jar}" fork="true" >
+            <arg value="-o"/>
+            <arg value="${mangled.bootdir}" />
+            <arg value="-f"/>
+            <arg value="${agent.conf.file}"/>
+            <arg value="${build.dir}/tmpB.jar"/>
+        </java>
+        <!-- Mangle test classes to mangled.testdir -->
+        <jar destfile="${build.dir}/tmpC.jar" basedir="${tests.classes.dir}"/>
+        <java jar="${agent.jar}" fork="true" >
+            <arg value="-o"/>
+            <arg value="${mangled.testdir}" />
+            <arg value="-f"/>
+            <arg value="${agent.conf.file}"/>
+            <arg value="${build.dir}/tmpC.jar"/>
+        </java>
     </target>
 
-    <target name="mangle-jdk-lite" depends="build-mangler">
-        <java jar="${agent.jar}" fork="true" >
-            <arg value="-o"/>
-            <arg value="${mangled.dir}" />
-            <arg value="-c"/>
-            <arg value="X"/>
-            <arg value="${java.home}/classes/java/util/ArrayList$SubList.class"/>
-        </java>
-        <java jar="${agent.jar}" fork="true" >
-            <arg value="-o"/>
-            <arg value="${mangled.dir}" />
-            <arg value="-c"/>
-            <arg value="X"/>
-            <arg value="${java.home}/classes/java/util/stream/SpinedBuffer.class"/>
-        </java>
-    </target>
-
+    <!--
+        Some tests are hostile to our serialization testing strategy; these are those where lambdas
+        have side-effects on captured arguments, and then we test properties of the captured arguments
+        separately.  This is because serialization/deserialization severs the aliasing that this test
+        strategy depends on.  So we mark and exclude these classes.
+    -->
     <target name="test-mangled" depends="test-compile, build-mangler" >
-        <testng classpathref="test.class.path" outputdir="${test.reports.dir}" >
-            <classfileset dir="${tests.classes.dir}" includes="org/openjdk/tests/java/**/*.class"
+        <testng classpathref="mangled.class.path" outputdir="${test.reports.dir}"
+                excludedgroups="serialization-hostile">
+            <classfileset dir="${mangled.testdir}" includes="org/openjdk/tests/java/**/*.class"
                           excludes="**/SerializedLambdaTest.class"/>
-            <classfileset dir="${boottests.classes.dir}" includes="java/**/*.class"/>
-            <jvmarg value="-Xbootclasspath/p:${mangled.dir}"/>
-            <jvmarg value="-Xbootclasspath/p:${boottests.classes.dir}"/>
-            <jvmarg value="-Xbootclasspath/p:${bootlib.classes.dir}"/>
+            <classfileset dir="${mangled.bootdir}" includes="java/util/stream/**/*.class"/>
+            <jvmarg value="-Xbootclasspath/p:${agent.jar}"/>
+            <jvmarg value="-Xbootclasspath/p:${mangled.bootdir}"/>
             <jvmarg value="-Xbootclasspath/p:${lib.testng.jar}"/>
             <jvmarg value="-ea" />
             <jvmarg value="-esa" />
             <jvmarg value="-Xverify:all" />
             <jvmarg value="-Xmx2500m" />
-            <jvmarg value="-javaagent:${agent.jar}=${agent.conf.file}"/>
+            <jvmarg value="-javaagent:${agent.jar}"/>
         </testng>
     </target>
 
     <target name="test-mangledp" depends="test-compile, build-mangler" >
-        <testng classpathref="test.class.path" outputdir="${test.reports.dir}" >
-            <classfileset dir="${tests.classes.dir}" includes="**/${test.pattern}.class"/>
-            <classfileset dir="${boottests.classes.dir}" includes="**/${test.pattern}.class"/>
-            <jvmarg value="-Xbootclasspath/p:${mangled.dir}"/>
-            <jvmarg value="-Xbootclasspath/p:${boottests.classes.dir}"/>
-            <jvmarg value="-Xbootclasspath/p:${bootlib.classes.dir}"/>
+        <testng classpathref="mangled.class.path" outputdir="${test.reports.dir}"
+                excludedgroups="serialization-hostile">
+            <classfileset dir="${mangled.testdir}" includes="**/${test.pattern}.class"/>
+            <classfileset dir="${mangled.bootdir}" includes="java/util/stream/**/${test.pattern}.class"/>
+            <jvmarg value="-Xbootclasspath/p:${agent.jar}"/>
+            <jvmarg value="-Xbootclasspath/p:${mangled.bootdir}"/>
             <jvmarg value="-Xbootclasspath/p:${lib.testng.jar}"/>
             <jvmarg value="-ea" />
             <jvmarg value="-esa" />
             <jvmarg value="-Xverify:all" />
             <jvmarg value="-Xmx2500m" />
-            <jvmarg value="-javaagent:${agent.jar}=${agent.conf.file}"/>
+            <jvmarg value="-javaagent:${agent.jar}"/>
         </testng>
     </target>
     <!-- mangler related,  end -->
--- a/test-ng/tests/org/openjdk/tests/java/lang/invoke/DeserializeMethodTest.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/tests/org/openjdk/tests/java/lang/invoke/DeserializeMethodTest.java	Tue Mar 12 17:06:19 2013 -0700
@@ -33,12 +33,10 @@
 import static org.testng.Assert.fail;
 
 /**
- * TestDeserializeMethod
- *
- * @author Brian Goetz
+ * Ensure that the $deserializeLambda$ method is present when it should be, and absent otherwise
  */
 
-@Test
+@Test(groups = { "serialization-hostile" })
 public class DeserializeMethodTest {
     private void assertDeserializeMethod(Class<?> clazz, boolean expectedPresent) {
         try {
--- a/test-ng/tests/org/openjdk/tests/java/util/BitsetStreamTest.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/tests/org/openjdk/tests/java/util/BitsetStreamTest.java	Tue Mar 12 17:06:19 2013 -0700
@@ -24,7 +24,9 @@
  */
 package org.openjdk.tests.java.util;
 
+import java.util.Iterator;
 import java.util.PrimitiveIterator;
+import java.util.function.Consumer;
 import java.util.stream.StreamTestData;
 import java.util.stream.StreamTestDataProvider;
 import org.testng.annotations.Test;
@@ -53,7 +55,8 @@
     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
     public void testBitsetStream(String name, StreamTestData<Integer> data) {
         BitSet bs = new BitSet();
-        data.forEach(bs::set);
+        for (int i : data.stream().map(e -> (int) e).toArray())
+            bs.set(i);
 
         assertEquals(bs.cardinality(), data.stream().collect(Collectors.toSet()).size());
         assertEquals(bs.cardinality(), bs.stream().reduce(0, (s, i) -> s+1));
--- a/test-ng/tests/org/openjdk/tests/java/util/MapTest.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/tests/org/openjdk/tests/java/util/MapTest.java	Tue Mar 12 17:06:19 2013 -0700
@@ -78,7 +78,7 @@
         map = null;
     }
 
-    @Test
+    @Test(groups = { "serialization-hostile" })
     public void testForEach() {
         final Set<String> values = new HashSet<>(EXPECTED.size());
         map.forEach((k, v) -> {values.add(v);});
@@ -92,5 +92,4 @@
             assertEquals(entry.getValue(), EXPECTED.get(entry.getKey()).toUpperCase());
         }
     }
-
 }
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/CollectionAndMapModifyStreamTest.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/CollectionAndMapModifyStreamTest.java	Tue Mar 12 17:06:19 2013 -0700
@@ -78,7 +78,8 @@
         collections.add(new ConcurrentSkipListSet<>(content));
 
         ArrayBlockingQueue<Integer> arrayBlockingQueue = new ArrayBlockingQueue<>(content.size());
-        for (Integer i : content) arrayBlockingQueue.add(i);
+        for (Integer i : content)
+            arrayBlockingQueue.add(i);
         collections.add(arrayBlockingQueue);
         collections.add(new PriorityBlockingQueue<>(content));
         collections.add(new LinkedBlockingQueue<>(content));
@@ -145,12 +146,12 @@
         return params;
     }
 
-    @Test(dataProvider = "maps")
+    @Test(dataProvider = "maps", groups = { "serialization-hostile" })
     public void testMapKeysSizeRemove(String name, Supplier<Map<Integer, Integer>> c) {
         testCollectionSizeRemove(name + " key set", c.get().keySet());
     }
 
-    @Test(dataProvider = "maps")
+    @Test(dataProvider = "maps", groups = { "serialization-hostile" })
     public void testMapValuesSizeRemove(String name, Supplier<Map<Integer, Integer>> c) {
         testCollectionSizeRemove(name + " value set", c.get().values());
     }
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/ForEachOpTest.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/ForEachOpTest.java	Tue Mar 12 17:06:19 2013 -0700
@@ -44,6 +44,7 @@
 @Test
 public class ForEachOpTest extends OpTestCase {
 
+    @Test(groups = { "serialization-hostile" })
     public void testForEach() {
         exerciseTerminalOps(countTo(10),
                             s -> {
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/GroupByOpTest.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/GroupByOpTest.java	Tue Mar 12 17:06:19 2013 -0700
@@ -65,7 +65,9 @@
                 = Collectors.groupingBy(Functions.forPredicate(pEven, true, false));
 
         Map<Boolean, Collection<Integer>> m = collector.resultSupplier().get();
-        countTo(10).stream().forEach(e -> collector.accumulator().accept(m, e));
+        int[] ints = countTo(10).stream().map(e -> (int) e).toArray();
+        for (int i : ints)
+            collector.accumulator().accept(m, i);
 
         assertEquals(2, m.keySet().size());
         for(Collection<Integer> group : m.values()) {
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/IntSliceOpTest.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/IntSliceOpTest.java	Tue Mar 12 17:06:19 2013 -0700
@@ -189,6 +189,7 @@
         exerciseOps(Streams.intRange(1, 101).map(i -> 101 - i).toArray(), s -> s.limit(10).sorted());
     }
 
+    @Test(groups = { "serialization-hostile" })
     public void testLimitShortCircuit() {
         for (int l : Arrays.asList(0, 10)) {
             AtomicInteger ai = new AtomicInteger();
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/SequentialOpTest.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/SequentialOpTest.java	Tue Mar 12 17:06:19 2013 -0700
@@ -50,7 +50,8 @@
  */
 public class SequentialOpTest extends OpTestCase {
     @SuppressWarnings({"rawtypes", "unchecked"})
-    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class,
+          groups = { "serialization-hostile" })
     public void testLazy(String name, StreamTestData<Integer> data) {
         Function<Integer, Integer> id = Functions.identity();
         AtomicInteger counter = new AtomicInteger();
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/SliceOpTest.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/SliceOpTest.java	Tue Mar 12 17:06:19 2013 -0700
@@ -189,6 +189,7 @@
         exerciseOps(l, s -> s.limit(10).sorted(Comparators.naturalOrder()));
     }
 
+    @Test(groups = { "serialization-hostile" })
     public void testLimitShortCircuit() {
         for (int l : Arrays.asList(0, 10)) {
             AtomicInteger ai = new AtomicInteger();
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/SortedOpTest.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/SortedOpTest.java	Tue Mar 12 17:06:19 2013 -0700
@@ -57,6 +57,7 @@
         assertFalse(s.hasCharacteristic(Spliterator.SORTED));
     }
 
+    @Test(groups = { "serialization-hostile" })
     public void testSequentialShortCircuitTerminal() {
         // The sorted op for sequential evaluation will buffer all elements when accepting
         // then at the end sort those elements and push those elements downstream
@@ -152,6 +153,7 @@
 
     //
 
+    @Test(groups = { "serialization-hostile" })
     public void testIntSequentialShortCircuitTerminal() {
         int[] a = new int[]{5, 4, 3, 2, 1};
 
@@ -215,6 +217,7 @@
 
     //
 
+    @Test(groups = { "serialization-hostile" })
     public void testLongSequentialShortCircuitTerminal() {
         long[] a = new long[]{5, 4, 3, 2, 1};
 
@@ -278,6 +281,7 @@
 
     //
 
+    @Test(groups = { "serialization-hostile" })
     public void testDoubleSequentialShortCircuitTerminal() {
         double[] a = new double[]{5.0, 4.0, 3.0, 2.0, 1.0};
 
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/TabulatorsTest.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/TabulatorsTest.java	Tue Mar 12 17:06:19 2013 -0700
@@ -28,6 +28,7 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Map;
 import java.util.TreeMap;
 import java.util.concurrent.ConcurrentHashMap;
@@ -148,7 +149,8 @@
                 fail(String.format("Class mismatch in CollectionAssertion: %s, %s", clazz, value.getClass()));
             Stream<T> stream = source.get();
             Collection<T> result = clazz.newInstance();
-            stream.forEach(result::add);
+            for (Iterator<T> it = stream.iterator(); it.hasNext(); ) // avoid capturing result::add
+                result.add(it.next());
             if (StreamOpFlagTestHelper.isStreamOrdered(stream) && targetOrdered && ordered)
                 assertContents(value, result);
             else
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/TeeOpTest.java	Tue Mar 12 20:06:05 2013 +0800
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/TeeOpTest.java	Tue Mar 12 17:06:19 2013 -0700
@@ -41,6 +41,7 @@
 /**
  * TeeOpTest
  */
+@Test(groups = { "serialization-hostile" })
 public class TeeOpTest extends OpTestCase {
 
     public void testTee() {
@@ -83,11 +84,11 @@
         }
         final RecordingConsumer b = new RecordingConsumer();
 
-        withData(data).
-                stream(s -> s.peek(b)).
-                before(b::before).
-                after(b::after).
-                exercise();
+        withData(data)
+                .stream(s -> s.peek(b))
+                .before(b::before)
+                .after(b::after)
+                .exercise();
     }
 
     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
@@ -99,11 +100,11 @@
         }
         final RecordingConsumer b = new RecordingConsumer();
 
-        withData(data).
-                stream(s -> s.peek(b)).
-                before(b::before).
-                after(b::after).
-                exercise();
+        withData(data)
+                .stream(s -> s.peek(b))
+                .before(b::before)
+                .after(b::after)
+                .exercise();
     }
 
     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
@@ -115,11 +116,11 @@
         }
         final RecordingConsumer b = new RecordingConsumer();
 
-        withData(data).
-                stream(s -> s.peek(b)).
-                before(b::before).
-                after(b::after).
-                exercise();
+        withData(data)
+                .stream(s -> s.peek(b))
+                .before(b::before)
+                .after(b::after)
+                .exercise();
     }
 
     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
@@ -131,10 +132,10 @@
         }
         final RecordingConsumer b = new RecordingConsumer();
 
-        withData(data).
-                stream(s -> s.peek(b)).
-                before(b::before).
-                after(b::after).
-                exercise();
+        withData(data)
+                .stream(s -> s.peek(b))
+                .before(b::before)
+                .after(b::after)
+                .exercise();
     }
 }