All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.metafacture.triples.MemoryWarningSystem Maven / Gradle / Ivy

/*
 * Copyright 2016 Christoph Böhme
 *
 * Licensed 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.
 */
/*
 *  Code based on http://www.javaspecialists.eu/archive/Issue092.html
 */

package org.metafacture.triples;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryNotificationInfo;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryType;
import java.util.Collection;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.management.Notification;
import javax.management.NotificationEmitter;
import javax.management.NotificationListener;

/**
 * This memory warning system will call the listener when we exceed the
 * percentage of available memory specified. The class is static, since the
 * usage threshold can only be set to one number.
 */
final class MemoryWarningSystem {
    private static final MemoryPoolMXBean TENURED_GEN_POOL = findTenuredGenPool();
    private static final double DEFAULT_THRESHOLD = 0.8;
    private static final Collection LISTENERS = new CopyOnWriteArrayList();

    private MemoryWarningSystem() {
        // no instances
    }

    static {
        setUsageThreshold(DEFAULT_THRESHOLD);
        final MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();
        final NotificationEmitter emitter = (NotificationEmitter) mbean;
        emitter.addNotificationListener(new NotificationListener() {

            @Override
            public void handleNotification(final Notification notification, final Object handback) {
                if (notification.getType().equals(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED)) {
                    for (final Listener listener : getListeners()) {
                        listener.memoryLow(getUsedMemory(), getMaxMemory());
                    }
                }
            }
        }, null, null);
    }

    private static Collection getListeners() {
        return LISTENERS;
    }

    private static long getMaxMemory() {
        return TENURED_GEN_POOL.getUsage().getMax();
    }

    private static long getUsedMemory() {
        return TENURED_GEN_POOL.getUsage().getUsed();
    }

    static boolean addListener(final Listener listener) {
        return LISTENERS.add(listener);
    }

    static boolean removeListener(final Listener listener) {
        return LISTENERS.remove(listener);
    }

    private static void setUsageThreshold(final double threshold) {
        if (threshold <= 0.0 || threshold > 1.0) {
            throw new IllegalArgumentException("'threshold' must be in [0.0, 1.0]");
        }
        TENURED_GEN_POOL.setUsageThreshold((long) (getMaxMemory() * threshold));
    }

    /**
     * Tenured Space Pool can be determined by it being of type HEAP and by it
     * being possible to set the usage threshold.
     *
     * @return MXBean for the Tenured Space Pool
     */
    private static MemoryPoolMXBean findTenuredGenPool() {
        // I don't know whether this approach is better, or whether
        // we should rather check for the pool name "Tenured Gen"?
        for (final MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {
            if (pool.getType() == MemoryType.HEAP && pool.isUsageThresholdSupported()) {
                return pool;
            }
        }
        throw new AssertionError("Could not find tenured space");
    }

    /**
     * Interface for low memory listeners
     */
    interface Listener {
        void memoryLow(long usedMemory, long maxMemory);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy