1 /* 2 * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 8282252 27 * @summary Verify BigInteger objects are serialized properly. 28 */ 29 30 package test.java.math.BigInteger; 31 32 import java.math.*; 33 import java.io.*; 34 import java.util.Arrays; 35 import java.util.List; 36 37 public class SerializationTests { 38 main(String... args)39 public static void main(String... args) throws Exception { 40 checkBigIntegerSerialRoundTrip(); 41 checkBigIntegerSubSerialRoundTrip(); 42 } 43 checkSerialForm(BigInteger bi)44 private static void checkSerialForm(BigInteger bi) throws Exception { 45 checkSerialForm0(bi); 46 checkSerialForm0(bi.negate()); 47 } 48 checkSerialForm0(BigInteger bi)49 private static void checkSerialForm0(BigInteger bi) throws Exception { 50 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 51 try(ObjectOutputStream oos = new ObjectOutputStream(bos)) { 52 oos.writeObject(bi); 53 oos.flush(); 54 } 55 56 ObjectInputStream ois = new 57 ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); 58 BigInteger tmp = (BigInteger)ois.readObject(); 59 60 if (!bi.equals(tmp) || 61 bi.hashCode() != tmp.hashCode() || 62 bi.getClass() != tmp.getClass() || 63 // For extra measure, directly test equality of components 64 bi.signum() != tmp.signum() || 65 !Arrays.equals(bi.toByteArray(), (tmp.toByteArray())) ) { 66 System.err.print(" original : " + bi); 67 System.err.println(" (hash: 0x" + Integer.toHexString(bi.hashCode()) + ")"); 68 System.err.print("serialized : " + tmp); 69 System.err.println(" (hash: 0x" + Integer.toHexString(tmp.hashCode()) + ")"); 70 throw new RuntimeException("Bad serial roundtrip"); 71 } 72 } 73 checkBigIntegerSerialRoundTrip()74 private static void checkBigIntegerSerialRoundTrip() throws Exception { 75 var values = 76 List.of(BigInteger.ZERO, 77 BigInteger.ONE, 78 BigInteger.TWO, 79 BigInteger.TEN, 80 BigInteger.valueOf(100), 81 BigInteger.valueOf(Integer.MAX_VALUE), 82 BigInteger.valueOf(Long.MAX_VALUE-1), 83 new BigInteger("9223372036854775808")); // Long.MAX_VALUE + 1 84 85 for(BigInteger value : values) { 86 checkSerialForm(value); 87 } 88 } 89 90 // Subclass with specialized toString output 91 private static class BigIntegerSub extends BigInteger { BigIntegerSub(BigInteger bi)92 public BigIntegerSub(BigInteger bi) { 93 super(bi.toByteArray()); 94 } 95 96 @Override toString()97 public String toString() { 98 return Arrays.toString(toByteArray()); 99 } 100 } 101 102 // Subclass defining a serialVersionUID 103 private static class BigIntegerSubSVUID extends BigInteger { 104 @java.io.Serial 105 private static long serialVesionUID = 0x0123_4567_89ab_cdefL; 106 BigIntegerSubSVUID(BigInteger bi)107 public BigIntegerSubSVUID(BigInteger bi) { 108 super(bi.toByteArray()); 109 } 110 111 @Override toString()112 public String toString() { 113 return Arrays.toString(toByteArray()); 114 } 115 } 116 117 // Subclass defining writeReplace 118 private static class BigIntegerSubWR extends BigInteger { BigIntegerSubWR(BigInteger bi)119 public BigIntegerSubWR(BigInteger bi) { 120 super(bi.toByteArray()); 121 } 122 123 // Just return this; could use a serial proxy instead 124 @java.io.Serial writeReplace()125 private Object writeReplace() throws ObjectStreamException { 126 return this; 127 } 128 } 129 130 checkBigIntegerSubSerialRoundTrip()131 private static void checkBigIntegerSubSerialRoundTrip() throws Exception { 132 var values = List.of(BigInteger.ZERO, 133 BigInteger.ONE, 134 BigInteger.TEN, 135 new BigInteger("9223372036854775808")); // Long.MAX_VALUE + 1 136 137 for(var value : values) { 138 checkSerialForm(new BigIntegerSub(value)); 139 checkSerialForm(new BigIntegerSubSVUID(value)); 140 checkSerialForm(new BigIntegerSubWR(value)); 141 } 142 } 143 } 144