/* * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* @test * @bug 8026344 * @summary Exercise classes in j.u.c.atomic that use serialization proxies */ import java.util.concurrent.atomic.DoubleAdder; import java.util.concurrent.atomic.DoubleAccumulator; import java.util.concurrent.atomic.LongAdder; import java.util.concurrent.atomic.LongAccumulator; import java.util.function.DoubleBinaryOperator; import java.util.function.LongBinaryOperator; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.Serializable; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.IOException; /** * Basic test to exercise the j.u.c.atomic classes that use serialization * proxies. */ public class Serial { public static void main(String[] args) { testDoubleAdder(); testDoubleAccumulator(); testLongAdder(); testLongAccumulator(); } static void testDoubleAdder() { DoubleAdder a = new DoubleAdder(); a.add(20.1d); DoubleAdder result = echo(a); if (result.doubleValue() != a.doubleValue()) throw new RuntimeException("Unexpected doubleValue"); checkSerialClassName(a, "java.util.concurrent.atomic.DoubleAdder$SerializationProxy"); } static void testDoubleAccumulator() { DoubleBinaryOperator plus = (DoubleBinaryOperator & Serializable) (x, y) -> x + y; DoubleAccumulator a = new DoubleAccumulator(plus, 13.9d); a.accumulate(17.5d); DoubleAccumulator result = echo(a); if (result.get() != a.get()) throw new RuntimeException("Unexpected value"); a.reset(); result.reset(); if (result.get() != a.get()) throw new RuntimeException("Unexpected value after reset"); checkSerialClassName(a, "java.util.concurrent.atomic.DoubleAccumulator$SerializationProxy"); } static void testLongAdder() { LongAdder a = new LongAdder(); a.add(45); LongAdder result = echo(a); if (result.longValue() != a.longValue()) throw new RuntimeException("Unexpected longValue"); checkSerialClassName(a, "java.util.concurrent.atomic.LongAdder$SerializationProxy"); } static void testLongAccumulator() { LongBinaryOperator plus = (LongBinaryOperator & Serializable) (x, y) -> x + y; LongAccumulator a = new LongAccumulator(plus, -2); a.accumulate(34); LongAccumulator result = echo(a); if (result.get() != a.get()) throw new RuntimeException("Unexpected value"); a.reset(); result.reset(); if (result.get() != a.get()) throw new RuntimeException("Unexpected value after reset"); checkSerialClassName(a, "java.util.concurrent.atomic.LongAccumulator$SerializationProxy"); } /** * Serialize the given object, returning the reconstituted object. */ @SuppressWarnings("unchecked") static <T extends Serializable> T echo(T obj) { ByteArrayOutputStream out = new ByteArrayOutputStream(); try (ObjectOutputStream oos = new ObjectOutputStream(out)) { oos.writeObject(obj); } catch (IOException e) { throw new RuntimeException("Serialization failed: " + e); } ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); try (ObjectInputStream ois = new ObjectInputStream(in)) { return (T) ois.readObject(); } catch (IOException | ClassNotFoundException e) { throw new RuntimeException("Deserialization failed: " + e); } } /** * Checks that the given object serializes to the expected class. */ static void checkSerialClassName(Serializable obj, String expected) { String cn = serialClassName(obj); if (!cn.equals(expected)) throw new RuntimeException(obj.getClass() + " serialized as " + cn + ", expected " + expected); } /** * Returns the class name that the given object serializes as. */ static String serialClassName(Serializable obj) { ByteArrayOutputStream out = new ByteArrayOutputStream(); try (ObjectOutputStream oos = new ObjectOutputStream(out)) { oos.writeObject(obj); } catch (IOException e) { throw new RuntimeException("Serialization failed: " + e); } ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); try (DataInputStream dis = new DataInputStream(in)) { dis.readShort(); // STREAM_MAGIC dis.readShort(); // STREAM_VERSION dis.readByte(); // TC_OBJECT dis.readByte(); // TC_CLASSDESC return dis.readUTF(); // className } catch (IOException e) { throw new RuntimeException(e); } } }