|
36 | 36 | import java.util.Hashtable;
|
37 | 37 | import java.util.Iterator;
|
38 | 38 | import java.util.Map;
|
| 39 | +import java.util.concurrent.atomic.AtomicInteger; |
39 | 40 |
|
40 | 41 | import javax.management.Attribute;
|
41 | 42 | import javax.management.AttributeList;
|
@@ -1097,6 +1098,96 @@ public final void testThreadAllocationMetricsOnCurrentThread() {
|
1097 | 1098 | AssertJUnit.assertTrue(bytes5 >= bytes4);
|
1098 | 1099 | }
|
1099 | 1100 |
|
| 1101 | + private final void allocateAndWait(int allocCount, Object sync, AtomicInteger count) { |
| 1102 | + try { |
| 1103 | + ArrayList list = new ArrayList<>(); |
| 1104 | + |
| 1105 | + for (int i = 0; i < allocCount; i++) { |
| 1106 | + list.add(new Object[100]); |
| 1107 | + } |
| 1108 | + |
| 1109 | + count.getAndIncrement(); |
| 1110 | + |
| 1111 | + synchronized (sync) { |
| 1112 | + sync.wait(); |
| 1113 | + } |
| 1114 | + } catch (InterruptedException e) { |
| 1115 | + e.printStackTrace(); |
| 1116 | + AssertJUnit.fail(e.getMessage()); |
| 1117 | + } |
| 1118 | + } |
| 1119 | + |
| 1120 | + /** |
| 1121 | + * Allocate differing amounts of objects on each thread and ensure that |
| 1122 | + * threadMXbean getThreadAllocatedBytes correctly reports the relative |
| 1123 | + * allocated amounts. |
| 1124 | + * |
| 1125 | + * @throws InterruptedException |
| 1126 | + */ |
| 1127 | + @Test |
| 1128 | + public final void testThreadAllocationMetrics() throws InterruptedException { |
| 1129 | + com.sun.management.ThreadMXBean sunTB = (com.sun.management.ThreadMXBean)tb; |
| 1130 | + |
| 1131 | + final Object sync = new Object() {}; |
| 1132 | + final AtomicInteger count = new AtomicInteger(0); |
| 1133 | + |
| 1134 | + Thread t1 = new Thread(()->{ |
| 1135 | + allocateAndWait(1000, sync, count); |
| 1136 | + }); |
| 1137 | + |
| 1138 | + Thread t2 = new Thread(()->{ |
| 1139 | + allocateAndWait(2000, sync, count); |
| 1140 | + }); |
| 1141 | + |
| 1142 | + Thread t3 = new Thread(()->{ |
| 1143 | + allocateAndWait(1, sync, count); |
| 1144 | + }); |
| 1145 | + |
| 1146 | + t1.start(); |
| 1147 | + t2.start(); |
| 1148 | + t3.start(); |
| 1149 | + |
| 1150 | + Thread.yield(); |
| 1151 | + Thread.yield(); |
| 1152 | + Thread.yield(); |
| 1153 | + |
| 1154 | + /* Wait for threads to complete allocations or 10 seconds */ |
| 1155 | + for (int i = 0; (count.get() < 3) || (i < 100); i++) { |
| 1156 | + Thread.sleep(100); |
| 1157 | + } |
| 1158 | + |
| 1159 | + if (count.get() != 3) { |
| 1160 | + AssertJUnit.fail("Threads did not complete allocations in allotted time."); |
| 1161 | + } |
| 1162 | + |
| 1163 | + /* Allocation stats are updated after a GC. */ |
| 1164 | + System.gc(); |
| 1165 | + |
| 1166 | + /* Check stats with `long getThreadAllocatedBytes(long tid)`. */ |
| 1167 | + long t1Stats = sunTB.getThreadAllocatedBytes(t1.getId()); |
| 1168 | + long t2Stats = sunTB.getThreadAllocatedBytes(t2.getId()); |
| 1169 | + long t3Stats = sunTB.getThreadAllocatedBytes(t3.getId()); |
| 1170 | + |
| 1171 | + AssertJUnit.assertTrue(t2Stats > t1Stats); |
| 1172 | + AssertJUnit.assertTrue(t1Stats > t3Stats); |
| 1173 | + |
| 1174 | + /* Check stats with `long[] getThreadAllocatedBytes(long[] tids)`. */ |
| 1175 | + long[] threadIDs = new long[] {t1.getId(), t2.getId(), t3.getId()}; |
| 1176 | + long[] threadStats = sunTB.getThreadAllocatedBytes(threadIDs); |
| 1177 | + |
| 1178 | + AssertJUnit.assertTrue(threadStats[1] > threadStats[0]); |
| 1179 | + AssertJUnit.assertTrue(threadStats[0] > threadStats[2]); |
| 1180 | + |
| 1181 | + /* Wake up threads and wait for them to terminate */ |
| 1182 | + synchronized (sync) { |
| 1183 | + sync.notifyAll(); |
| 1184 | + } |
| 1185 | + |
| 1186 | + t1.join(); |
| 1187 | + t2.join(); |
| 1188 | + t3.join(); |
| 1189 | + } |
| 1190 | + |
1100 | 1191 | @Test
|
1101 | 1192 | public final void testGetAttributes() {
|
1102 | 1193 | AttributeList attributes = null;
|
|
0 commit comments