/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.mm.mminterface; import java.lang.management.MemoryType; import java.lang.management.MemoryUsage; import java.util.HashMap; import org.jikesrvm.mm.mminterface.Selected.Plan; import org.jikesrvm.mm.mmtk.FinalizableProcessor; import org.mmtk.policy.Space; import org.mmtk.utility.Conversions; import org.mmtk.utility.options.Options; import org.mmtk.utility.statistics.Stats; import org.vmmagic.unboxed.Extent; /** * Provides methods supporting all JMX beans that relate to memory. Functionality * for memory management beans generally requires interfacing with MMTk which is * why this class belongs to the MMTk-VM interface. * <p> * In JMX terms, the Jikes RVM provides only one memory manager (the garbage collector) * and several memory pools (each of which corresponds to exactly one MMTk space). * <p> * NOTE: Features related to memory usage are currently not implemented. */ public class JMXSupport { /** * We only provide one garbage collector because the choice of garbage collector * for the VM is fixed at build time. */ private static final String[] garbageCollectorNames = { Selected.name }; /** * The names of all memory managers that are not garbage collectors. * All of our memory managers are collectors so this is empty. */ private static final String[] memoryManagerNames = {}; /** * Maps a space name to its index in the space array. */ private static HashMap<String, Integer> pools; private static String[] poolNames; /** * The level of verbosity that was used in MMTk when verbosity was switched off. * It will be restored when verbosity is switched on again. We can do this * because no other part of the system ever switches the verbosity. */ private static int lastMMTkVerbosity; /** * Initializes data structures. * This needs to called before the application starts. */ public static void fullyBootedVM() { int spaceCount = Space.getSpaceCount(); pools = new HashMap<String, Integer>(spaceCount * 2); Space[] spaces = Space.getSpaces(); for (int i = 0; i < spaceCount; i++) { pools.put(spaces[i].getName(), i); } poolNames = pools.keySet().toArray(new String[spaceCount]); } public static String[] getGarbageCollectorNames() { return garbageCollectorNames; } public static String[] getMemoryManagerNames() { return memoryManagerNames; } /** * @param poolName the name of the pool * @return the name of the memory manager(s) of the pool (always * our single garbage collector, i.e. active plan) */ public static String[] getMemoryManagerNames(String poolName) { return garbageCollectorNames; } public static String[] getPoolNames() { return poolNames; } /** * Returns non-heap for immortal spaces and heap for non-immortal * spaces because objects can be added and remove from non-immortal * spaces. * * @param poolName the pool's name * @return the type of the memory pool */ public static MemoryType getType(String poolName) { Space space = getSpace(poolName); boolean immortal = space.isImmortal(); if (immortal) { return MemoryType.NON_HEAP; } else { return MemoryType.HEAP; } } private static Space getSpace(String poolName) { Space[] spaces = Space.getSpaces(); int poolIndex = pools.get(poolName); return spaces[poolIndex]; } /** * @param poolName a memory pool name * @return whether a space with the given name exists */ public static boolean isValid(String poolName) { return pools.get(poolName) != null; } public static long getReservedBytes(Space space) { int reservedPages = space.reservedPages(); return Conversions.pagesToBytes(reservedPages).toLong(); } public static long getComittedBytes(Space space) { int committedPages = space.committedPages(); return Conversions.pagesToBytes(committedPages).toLong(); } public static long getPoolExtent(Space space) { Extent poolExtent = space.getExtent(); return poolExtent.toLong(); } public static MemoryUsage getUsage(boolean immortal) { long committed = 0, used = 0, max = 0; int spaceCount = Space.getSpaceCount(); Space[] spaces = Space.getSpaces(); for (int index = 0; index < spaceCount; index++) { Space space = spaces[index]; if (space.isImmortal() == immortal) { used += getReservedBytes(space); committed += getComittedBytes(space); max += getPoolExtent(space); } } return new MemoryUsage(-1, used, committed, max); } public static MemoryUsage getUsage(String poolName) { Space space = getSpace(poolName); long reservedBytes = JMXSupport.getReservedBytes(space); long committedBytes = JMXSupport.getComittedBytes(space); long poolExtent = JMXSupport.getPoolExtent(space); return new MemoryUsage(-1, reservedBytes, committedBytes, poolExtent); } public static int getObjectPendingFinalizationCount() { return FinalizableProcessor.countReadyForFinalize(); } public static synchronized boolean isMMTkVerbose() { return Options.verbose.getValue() > 0; } /** * Sets the verbosity for MMTk. Verbosity in MMTk has several levels * so this method makes an effort to save the previous verbosity level * if possible. * * @param verbose {@code true} if verbosity is to be enabled, * {@code false} otherwise */ public static synchronized void setMMTkVerbose(boolean verbose) { int currentVerbosity = Options.verbose.getValue(); if (verbose == false) { if (currentVerbosity > 0) { lastMMTkVerbosity = currentVerbosity; Options.verbose.setValue(0); } // else: nothing to do, MMTk is already non-verbose } else { if (lastMMTkVerbosity > 0) { // Restore old verbosity value, if we have one Options.verbose.setValue(lastMMTkVerbosity); } else { // No old value, so we assume verbosity of 1 because that will get // us printouts of collection times Options.verbose.setValue(1); } } } public static long getCollectionCount() { return Stats.gcCount(); } public static long getCollectionTime() { return Math.round(Plan.totalTime.getTotalMillis()); } }