|
27 | 27 | * Common code for string deduplication tests |
28 | 28 | */ |
29 | 29 |
|
| 30 | +import com.sun.management.GarbageCollectionNotificationInfo; |
30 | 31 | import java.lang.reflect.*; |
| 32 | +import java.lang.management.*; |
31 | 33 | import java.util.*; |
| 34 | +import javax.management.*; |
| 35 | +import javax.management.openmbean.*; |
32 | 36 | import jdk.test.lib.process.ProcessTools; |
33 | 37 | import jdk.test.lib.process.OutputAnalyzer; |
34 | 38 | import sun.misc.*; |
@@ -89,21 +93,58 @@ private static void doFullGc(int numberOfTimes) { |
89 | 93 | } |
90 | 94 | } |
91 | 95 |
|
| 96 | + private static volatile int gcCount; |
| 97 | + private static NotificationListener listener = new NotificationListener() { |
| 98 | + @Override |
| 99 | + public void handleNotification(Notification n, Object o) { |
| 100 | + if (n.getType().equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) { |
| 101 | + GarbageCollectionNotificationInfo info = GarbageCollectionNotificationInfo.from((CompositeData) n.getUserData()); |
| 102 | + // Shenandoah and Z GC also report GC pauses, skip them |
| 103 | + if (info.getGcName().startsWith("Shenandoah") || info.getGcName().startsWith("ZGC")) { |
| 104 | + if ("end of GC cycle".equals(info.getGcAction())) { |
| 105 | + gcCount++; |
| 106 | + } |
| 107 | + } else { |
| 108 | + gcCount++; |
| 109 | + } |
| 110 | + } |
| 111 | + } |
| 112 | + }; |
| 113 | + |
| 114 | + private static void registerGCListener() { |
| 115 | + for (GarbageCollectorMXBean bean : ManagementFactory.getGarbageCollectorMXBeans()) { |
| 116 | + ((NotificationEmitter)bean).addNotificationListener(listener, null, null); |
| 117 | + } |
| 118 | + } |
| 119 | + |
| 120 | + private static void unregisterGCListener() { |
| 121 | + for (GarbageCollectorMXBean bean : ManagementFactory.getGarbageCollectorMXBeans()) { |
| 122 | + try { |
| 123 | + ((NotificationEmitter) bean).removeNotificationListener(listener, null, null); |
| 124 | + } catch (Exception e) { |
| 125 | + } |
| 126 | + } |
| 127 | + } |
| 128 | + |
92 | 129 | private static void doYoungGc(int numberOfTimes) { |
93 | | - // Provoke at least numberOfTimes young GCs |
94 | 130 | final int objectSize = 128; |
95 | | - final int maxObjectInYoung = (Xmn * MB) / objectSize; |
96 | 131 | List<List<String>> newStrings = new ArrayList<List<String>>(); |
97 | | - for (int i = 0; i < numberOfTimes; i++) { |
| 132 | + |
| 133 | + // Provoke at least numberOfTimes young GCs |
| 134 | + gcCount = 0; |
| 135 | + registerGCListener(); |
| 136 | + while (gcCount < numberOfTimes) { |
| 137 | + int currentCount = gcCount; |
98 | 138 | // Create some more strings for every collection, to ensure |
99 | 139 | // there will be deduplication work that will be reported. |
100 | 140 | newStrings.add(createStrings(SmallNumberOfStrings, SmallNumberOfStrings)); |
101 | | - System.out.println("Begin: Young GC " + (i + 1) + "/" + numberOfTimes); |
102 | | - for (int j = 0; j < maxObjectInYoung + 1; j++) { |
| 141 | + System.out.println("Begin: Young GC " + (currentCount + 1) + "/" + numberOfTimes); |
| 142 | + while (currentCount == gcCount) { |
103 | 143 | dummy = new byte[objectSize]; |
104 | 144 | } |
105 | | - System.out.println("End: Young GC " + (i + 1) + "/" + numberOfTimes); |
| 145 | + System.out.println("End: Young GC " + (currentCount + 1) + "/" + numberOfTimes); |
106 | 146 | } |
| 147 | + unregisterGCListener(); |
107 | 148 | } |
108 | 149 |
|
109 | 150 | private static void forceDeduplication(int ageThreshold, String gcType) { |
|
0 commit comments