2222import java .lang .management .MemoryType ;
2323import java .lang .management .MemoryUsage ;
2424import java .text .SimpleDateFormat ;
25+ import java .util .ArrayList ;
26+ import java .util .Arrays ;
27+ import java .util .LinkedHashSet ;
2528import java .util .List ;
2629import java .util .Set ;
2730import java .util .concurrent .Executors ;
2831import java .util .concurrent .RejectedExecutionException ;
2932import java .util .concurrent .ScheduledExecutorService ;
3033import java .util .concurrent .ThreadFactory ;
3134import java .util .concurrent .TimeUnit ;
32-
35+ import java . util . function . Function ;
3336import javax .management .ListenerNotFoundException ;
37+ import javax .management .MalformedObjectNameException ;
3438import javax .management .Notification ;
3539import javax .management .NotificationEmitter ;
3640import javax .management .NotificationListener ;
41+ import javax .management .ObjectName ;
3742
3843import com .gemstone .gemfire .CancelException ;
3944import com .gemstone .gemfire .SystemFailure ;
4247import com .gemstone .gemfire .distributed .internal .ProcessorKeeper21 ;
4348import com .gemstone .gemfire .distributed .internal .membership .InternalDistributedMember ;
4449import com .gemstone .gemfire .i18n .LogWriterI18n ;
50+ import com .gemstone .gemfire .internal .Assert ;
4551import com .gemstone .gemfire .internal .DiskCapacityMonitor ;
4652import com .gemstone .gemfire .internal .GemFireStatSampler ;
4753import com .gemstone .gemfire .internal .LocalStatListener ;
4854import com .gemstone .gemfire .internal .LogWriterImpl ;
4955import com .gemstone .gemfire .internal .SetUtils ;
5056import com .gemstone .gemfire .internal .StatisticsImpl ;
5157import com .gemstone .gemfire .internal .cache .GemFireCacheImpl ;
52- import com .gemstone .gemfire .internal .cache .PartitionedRegion ;
5358import com .gemstone .gemfire .internal .cache .control .InternalResourceManager .ResourceType ;
5459import com .gemstone .gemfire .internal .cache .control .MemoryThresholds .MemoryState ;
5560import com .gemstone .gemfire .internal .cache .control .ResourceAdvisor .ResourceManagerProfile ;
@@ -152,13 +157,14 @@ public final class HeapMemoryMonitor implements NotificationListener,
152157 private static final long edenAndSurvivorPoolMaxMemory ;
153158
154159 static {
155- MemoryPoolMXBean matchingTenuredMemoryPoolMXBean = null ;
160+ ArrayList <MemoryPoolMXBean > matchingTenuredMemoryPoolMXBeans =
161+ new ArrayList <>(2 );
156162 MemoryPoolMXBean matchingEdenMemoryPoolMXBean = null ;
157163 MemoryPoolMXBean matchingSurvivorPoolMXBean = null ;
158164 for (MemoryPoolMXBean memoryPoolMXBean : ManagementFactory .getMemoryPoolMXBeans ()) {
159165 if (isTenured (memoryPoolMXBean )) {
160166 if (memoryPoolMXBean .isUsageThresholdSupported ()) {
161- matchingTenuredMemoryPoolMXBean = memoryPoolMXBean ;
167+ matchingTenuredMemoryPoolMXBeans . add ( memoryPoolMXBean ) ;
162168 }
163169 }
164170 else if (isEden (memoryPoolMXBean )) {
@@ -169,22 +175,26 @@ else if (isSurvivor(memoryPoolMXBean)) {
169175 }
170176 }
171177
172- tenuredMemoryPoolMXBean = matchingTenuredMemoryPoolMXBean ;
173178 edenMemoryPoolMXBean = matchingEdenMemoryPoolMXBean ;
174179 survivorPoolMXBean = matchingSurvivorPoolMXBean ;
175180
176- if (tenuredMemoryPoolMXBean == null ) {
181+ if (matchingTenuredMemoryPoolMXBeans . isEmpty () ) {
177182 LogWriterI18n logger = LogService .logger ();
178183 logger .error (LocalizedStrings .HeapMemoryMonitor_NO_POOL_FOUND_POOLS_0 , getAllMemoryPoolNames ());
184+ tenuredMemoryPoolMXBean = null ;
185+ } else {
186+ tenuredMemoryPoolMXBean = matchingTenuredMemoryPoolMXBeans .size () == 1
187+ ? matchingTenuredMemoryPoolMXBeans .get (0 )
188+ : new CompositePoolMXBean ("tenured-composite" ,
189+ matchingTenuredMemoryPoolMXBeans .toArray (new MemoryPoolMXBean [0 ]));
179190 }
180191
181192 /*
182193 * Calculates the max memory for the tenured pool. Works around JDK bug:
183194 * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7078465 by getting max
184195 * memory from runtime and subtracting all other heap pools from it.
185196 */
186- if (tenuredMemoryPoolMXBean != null
187- && tenuredMemoryPoolMXBean .getUsage ().getMax () != -1 ) {
197+ if (tenuredMemoryPoolMXBean .getUsage ().getMax () != -1 ) {
188198 tenuredPoolMaxMemory = tenuredMemoryPoolMXBean .getUsage ().getMax ();
189199 }
190200 else {
@@ -232,14 +242,15 @@ static boolean isTenured(MemoryPoolMXBean memoryPoolMXBean) {
232242 }
233243
234244 String name = memoryPoolMXBean .getName ();
235-
245+
236246 return name .equals ("CMS Old Gen" ) // Sun Concurrent Mark Sweep GC
237247 || name .equals ("PS Old Gen" ) // Sun Parallel GC
238248 || name .equals ("G1 Old Gen" ) // Sun G1 GC
239249 || name .equals ("Old Space" ) // BEA JRockit 1.5, 1.6 GC
240250 || name .equals ("Tenured Gen" ) // Hitachi 1.5 GC
241251 || name .equals ("Java heap" ) // IBM 1.5, 1.6 GC
242-
252+ || name .equals ("tenured-SOA" ) // OpenJ9
253+ || name .equals ("tenured-LOA" ) // OpenJ9
243254 // Allow an unknown pool name to monitor
244255 || (HEAP_POOL != null && name .equals (HEAP_POOL ));
245256 }
@@ -260,11 +271,12 @@ static boolean isEden(MemoryPoolMXBean memoryPoolMXBean) {
260271
261272 String name = memoryPoolMXBean .getName ();
262273
263- return name .equals ("Par Eden Space" ) // Oracle ParNew with Concurrent Mark Sweep GC
264- || name .equals ("PS Eden Space" ) // Oracle Parallel GC
265- || name .equals ("G1 Eden" ) // Oracle G1 GC
266- //|| name.equals("Nursery") // BEA JRockit 1.5, 1.6 GC
267- || name .equals ("Eden Space" ) // Hitachi 1.5 GC
274+ return name .equals ("Par Eden Space" ) // Oracle ParNew with Concurrent Mark Sweep GC
275+ || name .equals ("PS Eden Space" ) // Oracle Parallel GC
276+ || name .equals ("G1 Eden" ) // Oracle G1 GC
277+ //|| name.equals("Nursery") // BEA JRockit 1.5, 1.6 GC
278+ || name .equals ("Eden Space" ) // Hitachi 1.5 GC
279+ || name .equals ("nursery-allocate" ) // OpenJ9
268280 // Allow an unknown pool name to monitor
269281 || (HEAP_EDEN_POOL != null && name .equals (HEAP_EDEN_POOL ));
270282 }
@@ -289,6 +301,7 @@ static boolean isSurvivor(MemoryPoolMXBean memoryPoolMXBean) {
289301 || name .equals ("PS Survivor Space" ) // Oracle Parallel GC
290302 || name .equals ("G1 Survivor" ) // Oracle G1 GC
291303 || name .equals ("Survivor Space" ) // Hitachi 1.5 GC
304+ || name .equals ("nursery-survivor" ) // OpenJ9
292305 // Allow an unknown pool name to monitor
293306 || (HEAP_SURVIVOR_POOL != null && name .equals (HEAP_SURVIVOR_POOL ));
294307 }
@@ -1181,4 +1194,190 @@ public boolean failMemoryRequest(long accountedMemory) {
11811194 return false ;
11821195 }
11831196 }
1197+
1198+ public static class CompositePoolMXBean implements MemoryPoolMXBean {
1199+
1200+ private final String name ;
1201+ private final String objectName ;
1202+ private final MemoryPoolMXBean [] pools ;
1203+
1204+ public CompositePoolMXBean (String name , MemoryPoolMXBean [] pools ) {
1205+ // all pool types must be same
1206+ Assert .assertTrue (pools .length > 1 );
1207+ MemoryType expectedType = pools [0 ].getType ();
1208+ for (int i = 1 ; i < pools .length ; i ++) {
1209+ Assert .assertTrue (pools [i ].getType ().equals (expectedType ));
1210+ }
1211+
1212+ this .name = name ;
1213+ this .objectName = ManagementFactory .MEMORY_POOL_MXBEAN_DOMAIN_TYPE +
1214+ ",name=" + name ;
1215+ this .pools = pools ;
1216+ }
1217+
1218+ private MemoryUsage combineMemoryUsage (
1219+ Function <MemoryPoolMXBean , MemoryUsage > getUsage ) {
1220+ long init = 0L ;
1221+ long used = 0L ;
1222+ long committed = 0L ;
1223+ long max = 0L ;
1224+ for (MemoryPoolMXBean pool : this .pools ) {
1225+ MemoryUsage usage = getUsage .apply (pool );
1226+ init += Math .max (0L , usage .getInit ());
1227+ used += usage .getUsed ();
1228+ committed += usage .getCommitted ();
1229+ max += Math .max (0L , usage .getMax ());
1230+ }
1231+ if (init == 0L ) init = -1L ;
1232+ if (max == 0L ) max = -1L ;
1233+ return new MemoryUsage (init , used , committed , max );
1234+ }
1235+
1236+ @ Override
1237+ public String getName () {
1238+ return this .name ;
1239+ }
1240+
1241+ @ Override
1242+ public MemoryType getType () {
1243+ return this .pools [0 ].getType ();
1244+ }
1245+
1246+ @ Override
1247+ public MemoryUsage getUsage () {
1248+ return combineMemoryUsage (MemoryPoolMXBean ::getUsage );
1249+ }
1250+
1251+ @ Override
1252+ public MemoryUsage getPeakUsage () {
1253+ return combineMemoryUsage (MemoryPoolMXBean ::getPeakUsage );
1254+ }
1255+
1256+ @ Override
1257+ public void resetPeakUsage () {
1258+ for (MemoryPoolMXBean pool : this .pools ) {
1259+ pool .resetPeakUsage ();
1260+ }
1261+ }
1262+
1263+ @ Override
1264+ public boolean isValid () {
1265+ for (MemoryPoolMXBean pool : this .pools ) {
1266+ if (!pool .isValid ()) return false ;
1267+ }
1268+ return true ;
1269+ }
1270+
1271+ @ Override
1272+ public String [] getMemoryManagerNames () {
1273+ LinkedHashSet <String > managers = new LinkedHashSet <>(this .pools .length );
1274+ for (MemoryPoolMXBean pool : this .pools ) {
1275+ managers .addAll (Arrays .asList (pool .getMemoryManagerNames ()));
1276+ }
1277+ // noinspection ToArrayCallWithZeroLengthArrayArgument
1278+ return managers .toArray (new String [managers .size ()]);
1279+ }
1280+
1281+ @ Override
1282+ public long getUsageThreshold () {
1283+ long usageThreshold = 0L ;
1284+ for (MemoryPoolMXBean pool : this .pools ) {
1285+ long threshold = pool .getUsageThreshold ();
1286+ if (threshold > 0L && (usageThreshold == 0L || threshold < usageThreshold )) {
1287+ usageThreshold = threshold ;
1288+ }
1289+ }
1290+ return usageThreshold ;
1291+ }
1292+
1293+ @ Override
1294+ public void setUsageThreshold (long threshold ) {
1295+ for (MemoryPoolMXBean pool : this .pools ) {
1296+ pool .setUsageThreshold (threshold );
1297+ }
1298+ }
1299+
1300+ @ Override
1301+ public boolean isUsageThresholdExceeded () {
1302+ for (MemoryPoolMXBean pool : this .pools ) {
1303+ if (pool .isUsageThresholdExceeded ()) return true ;
1304+ }
1305+ return false ;
1306+ }
1307+
1308+ @ Override
1309+ public long getUsageThresholdCount () {
1310+ long usageThresholdCount = 0L ;
1311+ for (MemoryPoolMXBean pool : this .pools ) {
1312+ usageThresholdCount += pool .getUsageThresholdCount ();
1313+ }
1314+ return usageThresholdCount ;
1315+ }
1316+
1317+ @ Override
1318+ public boolean isUsageThresholdSupported () {
1319+ for (MemoryPoolMXBean pool : this .pools ) {
1320+ if (!pool .isUsageThresholdSupported ()) return false ;
1321+ }
1322+ return true ;
1323+ }
1324+
1325+ @ Override
1326+ public long getCollectionUsageThreshold () {
1327+ long usageThreshold = 0L ;
1328+ for (MemoryPoolMXBean pool : this .pools ) {
1329+ long threshold = pool .getCollectionUsageThreshold ();
1330+ if (threshold > 0L && (usageThreshold == 0L || threshold < usageThreshold )) {
1331+ usageThreshold = threshold ;
1332+ }
1333+ }
1334+ return usageThreshold ;
1335+ }
1336+
1337+ @ Override
1338+ public void setCollectionUsageThreshold (long threshold ) {
1339+ for (MemoryPoolMXBean pool : this .pools ) {
1340+ pool .setCollectionUsageThreshold (threshold );
1341+ }
1342+ }
1343+
1344+ @ Override
1345+ public boolean isCollectionUsageThresholdExceeded () {
1346+ for (MemoryPoolMXBean pool : this .pools ) {
1347+ if (pool .isCollectionUsageThresholdExceeded ()) return true ;
1348+ }
1349+ return false ;
1350+ }
1351+
1352+ @ Override
1353+ public long getCollectionUsageThresholdCount () {
1354+ long usageThresholdCount = 0L ;
1355+ for (MemoryPoolMXBean pool : this .pools ) {
1356+ usageThresholdCount += pool .getCollectionUsageThresholdCount ();
1357+ }
1358+ return usageThresholdCount ;
1359+ }
1360+
1361+ @ Override
1362+ public MemoryUsage getCollectionUsage () {
1363+ return combineMemoryUsage (MemoryPoolMXBean ::getCollectionUsage );
1364+ }
1365+
1366+ @ Override
1367+ public boolean isCollectionUsageThresholdSupported () {
1368+ for (MemoryPoolMXBean pool : this .pools ) {
1369+ if (!pool .isCollectionUsageThresholdSupported ()) return false ;
1370+ }
1371+ return true ;
1372+ }
1373+
1374+ @ Override
1375+ public ObjectName getObjectName () {
1376+ try {
1377+ return ObjectName .getInstance (this .objectName );
1378+ } catch (MalformedObjectNameException e ) {
1379+ throw new IllegalArgumentException (e );
1380+ }
1381+ }
1382+ }
11841383}
0 commit comments