1 /*
 2  * Copyright (c) 2023, 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 import java.io.IOException;
25 import java.nio.charset.StandardCharsets;
26 
27 /*
28  * @test
29  * @bug 8077559
30  * @summary Tests Compact String for negative size.
31  * @requires vm.bits == 64 & os.maxMemory >= 4G
32  * @run main/othervm -XX:+CompactStrings -Xmx4g NegativeSize
33  * @run main/othervm -XX:-CompactStrings -Xmx4g NegativeSize
34  */
35 
36 // In Java8: java.lang.OutOfMemoryError: Java heap space
37 // In Java9+: was java.lang.NegativeArraySizeException: -1894967266
38 public class NegativeSize {
39 
40     static byte[] generateData() {
41         int asciisize = 1_200_000_000;
42         byte[] nonAscii = "非アスキー".getBytes();
43         int nonAsciiSize = nonAscii.length;
44         // 1 GB
45         byte[] arr = new byte[asciisize + nonAsciiSize];
46         for (int i=0; i<asciisize; ++i) {
47             arr[i] = (byte)('0' + (i % 40));
48         }
49         for(int i=0; i<nonAsciiSize; ++i) {
50             arr[i + asciisize] = nonAscii[i];
51         }
52         return arr;
53     }
54 
55 
56     public static void main(String[] args) throws IOException {
57 
58         try {
59             byte[] largeBytes = generateData();
60             String inStr = new String(largeBytes, StandardCharsets.UTF_8);
61             System.out.println(inStr.length());
62             System.out.println(inStr.substring(1_200_000_000));
63         } catch (OutOfMemoryError ex) {
64             if (ex.getMessage().startsWith("UTF16 String size is")) {
65                 System.out.println("Succeeded with OutOfMemoryError");
66             } else {
67                 throw new RuntimeException("Failed: Not the OutOfMemoryError expected", ex);
68             }
69         } catch (NegativeArraySizeException ex) {
70             throw new RuntimeException("Failed: Expected OutOfMemoryError", ex);
71         }
72     }
73 }
74 
75