1 /* 2 * Copyright (c) 2017, 2018 Red Hat, Inc. and/or its affiliates. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 * 22 */ 23 24 /* 25 * @test TestShenandoahStringDedup.java 26 * @summary Test Shenandoah string deduplication implementation 27 * @key gc 28 * 29 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCHeuristics=passive -XX:+ShenandoahDegeneratedGC -XX:+UseStringDeduplication -Xmx256M TestShenandoahStrDedup 30 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCHeuristics=passive -XX:-ShenandoahDegeneratedGC -XX:+UseStringDeduplication -Xmx256M TestShenandoahStrDedup 31 * 32 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -Xmx256M TestShenandoahStrDedup 33 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCHeuristics=aggressive -XX:+UseStringDeduplication -Xmx256M TestShenandoahStrDedup 34 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCHeuristics=compact -XX:+UseStringDeduplication -Xmx256M TestShenandoahStrDedup 35 */ 36 37 import java.lang.reflect.*; 38 import java.util.*; 39 import sun.misc.*; 40 41 public class TestShenandoahStrDedup { 42 private static Field valueField; 43 private static Unsafe unsafe; 44 45 private static final int UniqueStrings = 20; 46 static { 47 try { 48 Field field = Unsafe.class.getDeclaredField("theUnsafe"); 49 field.setAccessible(true); 50 unsafe = (Unsafe)field.get(null); 51 52 valueField = String.class.getDeclaredField("value"); 53 valueField.setAccessible(true); 54 } catch (Exception e) { 55 throw new RuntimeException(e); 56 } 57 } 58 59 private static Object getValue(String string) { 60 try { 61 return valueField.get(string); 62 } catch (Exception e) { 63 throw new RuntimeException(e); 64 } 65 } 66 67 static class StringAndId { 68 private String str; 69 private int id; 70 public StringAndId(String str, int id) { 71 this.str = str; 72 this.id = id; 73 } 74 75 public String str() { return str; } 76 public int id() { return id; } 77 } 78 79 private static void generateStrings(ArrayList<StringAndId> strs, int unique_strs) { 80 Random rn = new Random(); 81 for (int u = 0; u < unique_strs; u ++) { 82 int n = rn.nextInt() % 10; 83 n = Math.max(n, 2); 84 for (int index = 0; index < n; index ++) { 85 strs.add(new StringAndId("Unique String " + u, u)); 86 } 87 } 88 } 89 90 private static int verifyDedepString(ArrayList<StringAndId> strs) { 91 HashMap<Object, StringAndId> seen = new HashMap<>(); 92 int total = 0; 93 int dedup = 0; 94 95 for (StringAndId item : strs) { 96 total ++; 97 StringAndId existing_item = seen.get(getValue(item.str())); 98 if (existing_item == null) { 99 seen.put(getValue(item.str()), item); 100 } else { 101 if (item.id() != existing_item.id() || 102 !item.str().equals(existing_item.str())) { 103 System.out.println("StringDedup error:"); 104 System.out.println("String: " + item.str() + " != " + existing_item.str()); 105 throw new RuntimeException("StringDedup Test failed"); 106 } else { 107 dedup ++; 108 } 109 } 110 } 111 System.out.println("Dedup: " + dedup + "/" + total + " unique: " + (total - dedup)); 112 return (total - dedup); 113 } 114 115 public static void main(String[] args) { 116 ArrayList<StringAndId> astrs = new ArrayList<>(); 117 generateStrings(astrs, UniqueStrings); 118 System.gc(); 119 System.gc(); 120 System.gc(); 121 System.gc(); 122 System.gc(); 123 124 if (verifyDedepString(astrs) != UniqueStrings) { 125 // Can not guarantee all strings are deduplicated, there can 126 // still have pending items in queues. 127 System.out.println("Not all strings are deduplicated"); 128 } 129 } 130 }