/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.cache.management; import org.apache.geode.LogWriter; import org.apache.geode.cache.*; import org.apache.geode.distributed.ConfigurationProperties; import org.apache.geode.distributed.DistributedSystem; import javax.management.Notification; import javax.management.NotificationEmitter; import javax.management.NotificationListener; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.MemoryPoolMXBean; import java.lang.management.MemoryType; import java.util.List; import java.util.Properties; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT; /** * An test class for exploring the various notification listener behaviors * * Run it like this: * * java -cp geode-dependencies.jar:. -Dgemfire.log-file=system.log * -Dgemfire.statistic-archive-file=statsArchive.gfs * org.apache.geode.cache.control.MXMemoryPoolListenerExample * * @since GemFire 6.0 */ public class MXMemoryPoolListenerExample implements NotificationListener { private AtomicBoolean critical = new AtomicBoolean(); final private LogWriter logger; /** * @param ds */ public MXMemoryPoolListenerExample(DistributedSystem ds) { this.logger = ds.getLogWriter(); } /* * (non-Javadoc) * * @see javax.management.NotificationListener#handleNotification(javax.management.Notification, * java.lang.Object) */ public void handleNotification(Notification arg0, Object arg1) { this.logger.info("Notification: " + arg0 + "; o: " + arg1 + "; m: " + arg0.getMessage()); this.critical.set(true); } public static void main(String args[]) { final MemoryMXBean mbean = ManagementFactory.getMemoryMXBean(); final double threshold; { double t = 0.8; if (args.length > 0) { try { t = Integer.parseInt(args[0]) / 100; } catch (NumberFormatException useDefault) { } } if (t < 0.0 || t > 1.0) { throw new IllegalArgumentException("Theshold must be >= 0 and <= 100"); } threshold = t; } final int percentTenured; { int p = 100; if (args.length > 1) { try { p = Integer.parseInt(args[1]); } catch (NumberFormatException useDefault) { } } if (p > 100 || p < 0) { throw new IllegalArgumentException("Percent Tenured must be >= 0 and <= 100"); } percentTenured = p; } Properties dsProps = new Properties(); dsProps.setProperty(MCAST_PORT, "0"); // Loner dsProps.setProperty(ConfigurationProperties.LOG_LEVEL, "info"); dsProps.setProperty(ConfigurationProperties.STATISTIC_SAMPLE_RATE, "200"); dsProps.setProperty(ConfigurationProperties.ENABLE_TIME_STATISTICS, "true"); dsProps.setProperty(ConfigurationProperties.STATISTIC_SAMPLING_ENABLED, "true"); DistributedSystem ds = DistributedSystem.connect(dsProps); final LogWriter logger = ds.getLogWriter(); logger.info("Usage threshold: " + threshold + "; percent tenured: " + percentTenured + "; Runtime Maximum memory: " + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + "Mb" + "; Heap Maximum memory: " + (mbean.getHeapMemoryUsage().getMax() / (1024 * 1024)) + "Mb"); MXMemoryPoolListenerExample me = new MXMemoryPoolListenerExample(ds); // Register this listener to NotificationEmitter NotificationEmitter emitter = (NotificationEmitter) mbean; emitter.addNotificationListener(me, null, null); List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans(); for (MemoryPoolMXBean p : pools) { if (p.isCollectionUsageThresholdSupported()) { // p.setCollectionUsageThreshold(0); logger.info("Pool which supports collection usage threshold: " + p.getName() + "; " + p.getCollectionUsage()); } // On JRockit do not set the usage threshold on the Nursery pool if (p.getType().equals(MemoryType.HEAP) && p.isUsageThresholdSupported() && !p.getName().startsWith("Nursery")) { int byteThreshold = (int) Math.ceil(threshold * p.getUsage().getMax()); logger.info("Setting threshold " + (byteThreshold / (1024 * 1024)) + "Mb on: " + p.getName() + "; " + p.getCollectionUsage()); p.setUsageThreshold(byteThreshold); } } final Cache c = CacheFactory.create(ds); new MemoryHog("hog_1", c, me.critical).consumeMemory(percentTenured).printTenuredSize(); ds.disconnect(); } public static class MemoryHog { private final String name; private final Region tenuredData; private final Cache cache; private final AtomicBoolean criticalState; public MemoryHog(String n, Cache c, AtomicBoolean critical) { this.name = n; this.cache = c; this.tenuredData = new RegionFactory().setScope(Scope.LOCAL).create(this.name); this.criticalState = critical; } /** * @param percentTenured */ public MemoryHog consumeMemory(final int percentTenured) { final long maxSecondsToRun = 180; final LogWriter logger = this.cache.getLogger(); final long start = System.nanoTime(); for (int i = 100;; i++) { // Create garbage byte[] val = new byte[1012]; // 1024 less 4 bytes for obj ref, less 8 bytes for Integer key // == 1012 // Some random usage of the data to prevent optimization val[percentTenured] = (byte) i; if (percentTenured > 0 && (i % 100) <= percentTenured) { // Grow heap this.tenuredData.put(new Integer(i), val); } if (i % 1000 == 0) { long runTime = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start); if (runTime > maxSecondsToRun) { logger.info(this.name + ": Ending consume loop after " + runTime + "s"); break; } } if (this.criticalState.get()) { logger.info(this.name + ": Clearing tenured data: size=" + (this.tenuredData.size() / 1024) + "Mb"); this.tenuredData.clear(); this.criticalState.set(false); try { Thread.sleep(250); } catch (InterruptedException ie) { } } } return this; } public MemoryHog printTenuredSize() { this.cache.getLogger().info( "Tenured data size: " + this.tenuredData.getName() + ": " + this.tenuredData.size()); return this; } } }