org.apache.activemq.artemis.core.server.MemoryManager Maven / Gradle / Ivy
/*
* 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.activemq.artemis.core.server;
import org.apache.activemq.artemis.utils.SizeFormatterUtil;
import org.jboss.logging.Logger;
/**
* A memory usage watcher.
*
* This class will run a thread monitoring memory usage and log warnings in case we are low on
* memory.
*/
public class MemoryManager implements ActiveMQComponent {
private static final Logger logger = Logger.getLogger(MemoryManager.class);
private final Runtime runtime;
private final long measureInterval;
private final int memoryWarningThreshold;
private volatile boolean started;
private Thread thread;
private volatile boolean low;
public MemoryManager(final int memoryWarningThreshold, final long measureInterval) {
runtime = Runtime.getRuntime();
this.measureInterval = measureInterval;
this.memoryWarningThreshold = memoryWarningThreshold;
}
public boolean isMemoryLow() {
return low;
}
@Override
public synchronized boolean isStarted() {
return started;
}
@Override
public synchronized void start() {
logger.debug("Starting MemoryManager with MEASURE_INTERVAL: " + measureInterval +
" FREE_MEMORY_PERCENT: " +
memoryWarningThreshold);
if (started) {
// Already started
return;
}
started = true;
thread = new Thread(new MemoryRunnable(), "activemq-memory-manager-thread");
thread.setDaemon(true);
thread.start();
}
@Override
public synchronized void stop() {
if (!started) {
// Already stopped
return;
}
started = false;
thread.interrupt();
try {
thread.join();
} catch (InterruptedException ignore) {
}
}
private class MemoryRunnable implements Runnable {
@Override
public void run() {
while (true) {
try {
if (thread.isInterrupted() && !started) {
break;
}
Thread.sleep(measureInterval);
} catch (InterruptedException ignore) {
if (!started) {
return;
}
}
long maxMemory = runtime.maxMemory();
long totalMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
long availableMemory = freeMemory + maxMemory - totalMemory;
double availableMemoryPercent = 100.0 * availableMemory / maxMemory;
StringBuilder info = new StringBuilder();
info.append(String.format("free memory: %s%n", SizeFormatterUtil.sizeof(freeMemory)));
info.append(String.format("max memory: %s%n", SizeFormatterUtil.sizeof(maxMemory)));
info.append(String.format("total memory: %s%n", SizeFormatterUtil.sizeof(totalMemory)));
info.append(String.format("available memory: %.2f%%%n", availableMemoryPercent));
if (logger.isDebugEnabled()) {
logger.debug(info);
}
if (availableMemoryPercent <= memoryWarningThreshold) {
ActiveMQServerLogger.LOGGER.memoryError(memoryWarningThreshold, info.toString());
low = true;
} else {
low = false;
}
}
}
}
}