001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.mm.mminterface; 014 015import java.lang.management.MemoryType; 016import java.lang.management.MemoryUsage; 017import java.util.HashMap; 018 019import org.jikesrvm.mm.mminterface.Selected.Plan; 020import org.jikesrvm.mm.mmtk.FinalizableProcessor; 021import org.mmtk.policy.Space; 022import org.mmtk.utility.Conversions; 023import org.mmtk.utility.options.Options; 024import org.mmtk.utility.statistics.Stats; 025import org.vmmagic.unboxed.Extent; 026 027/** 028 * Provides methods supporting all JMX beans that relate to memory. Functionality 029 * for memory management beans generally requires interfacing with MMTk which is 030 * why this class belongs to the MMTk-VM interface. 031 * <p> 032 * In JMX terms, the Jikes RVM provides only one memory manager (the garbage collector) 033 * and several memory pools (each of which corresponds to exactly one MMTk space). 034 * <p> 035 * NOTE: Features related to memory usage are currently not implemented. 036 */ 037public class JMXSupport { 038 039 /** 040 * We only provide one garbage collector because the choice of garbage collector 041 * for the VM is fixed at build time. 042 */ 043 private static final String[] garbageCollectorNames = { Selected.name }; 044 045 /** 046 * The names of all memory managers that are not garbage collectors. 047 * All of our memory managers are collectors so this is empty. 048 */ 049 private static final String[] memoryManagerNames = {}; 050 051 /** 052 * Maps a space name to its index in the space array. 053 */ 054 private static HashMap<String, Integer> pools; 055 056 private static String[] poolNames; 057 058 /** 059 * The level of verbosity that was used in MMTk when verbosity was switched off. 060 * It will be restored when verbosity is switched on again. We can do this 061 * because no other part of the system ever switches the verbosity. 062 */ 063 private static int lastMMTkVerbosity; 064 065 /** 066 * Initializes data structures. 067 * This needs to called before the application starts. 068 */ 069 public static void fullyBootedVM() { 070 int spaceCount = Space.getSpaceCount(); 071 pools = new HashMap<String, Integer>(spaceCount * 2); 072 Space[] spaces = Space.getSpaces(); 073 for (int i = 0; i < spaceCount; i++) { 074 pools.put(spaces[i].getName(), i); 075 } 076 poolNames = pools.keySet().toArray(new String[spaceCount]); 077 } 078 079 public static String[] getGarbageCollectorNames() { 080 return garbageCollectorNames; 081 } 082 083 public static String[] getMemoryManagerNames() { 084 return memoryManagerNames; 085 } 086 087 /** 088 * @param poolName the name of the pool 089 * @return the name of the memory manager(s) of the pool (always 090 * our single garbage collector, i.e. active plan) 091 */ 092 public static String[] getMemoryManagerNames(String poolName) { 093 return garbageCollectorNames; 094 } 095 096 public static String[] getPoolNames() { 097 return poolNames; 098 } 099 100 /** 101 * Returns non-heap for immortal spaces and heap for non-immortal 102 * spaces because objects can be added and remove from non-immortal 103 * spaces. 104 * 105 * @param poolName the pool's name 106 * @return the type of the memory pool 107 */ 108 public static MemoryType getType(String poolName) { 109 Space space = getSpace(poolName); 110 boolean immortal = space.isImmortal(); 111 if (immortal) { 112 return MemoryType.NON_HEAP; 113 } else { 114 return MemoryType.HEAP; 115 } 116 } 117 118 private static Space getSpace(String poolName) { 119 Space[] spaces = Space.getSpaces(); 120 int poolIndex = pools.get(poolName); 121 return spaces[poolIndex]; 122 } 123 124 /** 125 * @param poolName a memory pool name 126 * @return whether a space with the given name exists 127 */ 128 public static boolean isValid(String poolName) { 129 return pools.get(poolName) != null; 130 } 131 132 public static long getReservedBytes(Space space) { 133 int reservedPages = space.reservedPages(); 134 return Conversions.pagesToBytes(reservedPages).toLong(); 135 } 136 137 public static long getComittedBytes(Space space) { 138 int committedPages = space.committedPages(); 139 return Conversions.pagesToBytes(committedPages).toLong(); 140 } 141 142 public static long getPoolExtent(Space space) { 143 Extent poolExtent = space.getExtent(); 144 return poolExtent.toLong(); 145 } 146 147 public static MemoryUsage getUsage(boolean immortal) { 148 long committed = 0, used = 0, max = 0; 149 int spaceCount = Space.getSpaceCount(); 150 Space[] spaces = Space.getSpaces(); 151 for (int index = 0; index < spaceCount; index++) { 152 Space space = spaces[index]; 153 if (space.isImmortal() == immortal) { 154 used += getReservedBytes(space); 155 committed += getComittedBytes(space); 156 max += getPoolExtent(space); 157 } 158 } 159 return new MemoryUsage(-1, used, committed, max); 160 } 161 162 public static MemoryUsage getUsage(String poolName) { 163 Space space = getSpace(poolName); 164 long reservedBytes = JMXSupport.getReservedBytes(space); 165 long committedBytes = JMXSupport.getComittedBytes(space); 166 long poolExtent = JMXSupport.getPoolExtent(space); 167 return new MemoryUsage(-1, reservedBytes, committedBytes, poolExtent); 168 } 169 170 public static int getObjectPendingFinalizationCount() { 171 return FinalizableProcessor.countReadyForFinalize(); 172 } 173 174 public static synchronized boolean isMMTkVerbose() { 175 return Options.verbose.getValue() > 0; 176 } 177 178 /** 179 * Sets the verbosity for MMTk. Verbosity in MMTk has several levels 180 * so this method makes an effort to save the previous verbosity level 181 * if possible. 182 * 183 * @param verbose {@code true} if verbosity is to be enabled, 184 * {@code false} otherwise 185 */ 186 public static synchronized void setMMTkVerbose(boolean verbose) { 187 int currentVerbosity = Options.verbose.getValue(); 188 if (verbose == false) { 189 if (currentVerbosity > 0) { 190 lastMMTkVerbosity = currentVerbosity; 191 Options.verbose.setValue(0); 192 } 193 // else: nothing to do, MMTk is already non-verbose 194 } else { 195 if (lastMMTkVerbosity > 0) { 196 // Restore old verbosity value, if we have one 197 Options.verbose.setValue(lastMMTkVerbosity); 198 } else { 199 // No old value, so we assume verbosity of 1 because that will get 200 // us printouts of collection times 201 Options.verbose.setValue(1); 202 } 203 } 204 } 205 206 public static long getCollectionCount() { 207 return Stats.gcCount(); 208 } 209 210 public static long getCollectionTime() { 211 return Math.round(Plan.totalTime.getTotalMillis()); 212 } 213 214}