1 /* 2 * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.management; 27 28 import java.lang.management.MemoryUsage; 29 import java.lang.reflect.Method; 30 import java.lang.reflect.Field; 31 import java.util.Iterator; 32 import java.util.Map; 33 import java.util.HashMap; 34 import java.util.List; 35 import java.util.Collections; 36 import java.io.InvalidObjectException; 37 import javax.management.openmbean.CompositeType; 38 import javax.management.openmbean.CompositeData; 39 import javax.management.openmbean.CompositeDataSupport; 40 import javax.management.openmbean.TabularData; 41 import javax.management.openmbean.SimpleType; 42 import javax.management.openmbean.OpenType; 43 import javax.management.openmbean.OpenDataException; 44 import com.sun.management.GcInfo; 45 import com.sun.management.GarbageCollectionNotificationInfo; 46 import java.security.AccessController; 47 import java.security.PrivilegedAction; 48 49 /** 50 * A CompositeData for GcInfo for the local management support. 51 * This class avoids the performance penalty paid to the 52 * construction of a CompositeData use in the local case. 53 */ 54 public class GcInfoCompositeData extends LazyCompositeData { 55 private final GcInfo info; 56 private final GcInfoBuilder builder; 57 private final Object[] gcExtItemValues; 58 59 public GcInfoCompositeData(GcInfo info, 60 GcInfoBuilder builder, 61 Object[] gcExtItemValues) { 62 this.info = info; 63 this.builder = builder; 64 this.gcExtItemValues = gcExtItemValues; 65 } 66 67 public GcInfo getGcInfo() { 68 return info; 69 } 70 71 public static CompositeData toCompositeData(final GcInfo info) { 72 final GcInfoBuilder builder = AccessController.doPrivileged (new PrivilegedAction<GcInfoBuilder>() { 73 public GcInfoBuilder run() { 74 try { 75 Class cl = Class.forName("com.sun.management.GcInfo"); 76 Field f = cl.getDeclaredField("builder"); 77 f.setAccessible(true); 78 return (GcInfoBuilder)f.get(info); 79 } catch(ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { 80 return null; 81 } 82 } 83 }); 84 final Object[] extAttr = AccessController.doPrivileged (new PrivilegedAction<Object[]>() { 85 public Object[] run() { 86 try { 87 Class cl = Class.forName("com.sun.management.GcInfo"); 88 Field f = cl.getDeclaredField("extAttributes"); 89 f.setAccessible(true); 90 return (Object[])f.get(info); 91 } catch(ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { 92 return null; 93 } 94 } 95 }); 96 GcInfoCompositeData gcicd = 97 new GcInfoCompositeData(info,builder,extAttr); 98 return gcicd.getCompositeData(); 99 } 100 101 protected CompositeData getCompositeData() { 102 // CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH 103 // baseGcInfoItemNames! 104 final Object[] baseGcInfoItemValues; 105 106 try { 107 baseGcInfoItemValues = new Object[] { 108 new Long(info.getId()), 109 new Long(info.getStartTime()), 110 new Long(info.getEndTime()), 111 new Long(info.getDuration()), 112 memoryUsageMapType.toOpenTypeData(info.getMemoryUsageBeforeGc()), 113 memoryUsageMapType.toOpenTypeData(info.getMemoryUsageAfterGc()), 114 }; 115 } catch (OpenDataException e) { 116 // Should never reach here 117 throw new AssertionError(e); 118 } 119 120 // Get the item values for the extension attributes 121 final int gcExtItemCount = builder.getGcExtItemCount(); 122 if (gcExtItemCount == 0 && 123 gcExtItemValues != null && gcExtItemValues.length != 0) { 124 throw new AssertionError("Unexpected Gc Extension Item Values"); 125 } 126 127 if (gcExtItemCount > 0 && (gcExtItemValues == null || 128 gcExtItemCount != gcExtItemValues.length)) { 129 throw new AssertionError("Unmatched Gc Extension Item Values"); 130 } 131 132 Object[] values = new Object[baseGcInfoItemValues.length + 133 gcExtItemCount]; 134 System.arraycopy(baseGcInfoItemValues, 0, values, 0, 135 baseGcInfoItemValues.length); 136 137 if (gcExtItemCount > 0) { 138 System.arraycopy(gcExtItemValues, 0, values, 139 baseGcInfoItemValues.length, gcExtItemCount); 140 } 141 142 try { 143 return new CompositeDataSupport(builder.getGcInfoCompositeType(), 144 builder.getItemNames(), 145 values); 146 } catch (OpenDataException e) { 147 // Should never reach here 148 throw new AssertionError(e); 149 } 150 } 151 152 private static final String ID = "id"; 153 private static final String START_TIME = "startTime"; 154 private static final String END_TIME = "endTime"; 155 private static final String DURATION = "duration"; 156 private static final String MEMORY_USAGE_BEFORE_GC = "memoryUsageBeforeGc"; 157 private static final String MEMORY_USAGE_AFTER_GC = "memoryUsageAfterGc"; 158 159 private static final String[] baseGcInfoItemNames = { 160 ID, 161 START_TIME, 162 END_TIME, 163 DURATION, 164 MEMORY_USAGE_BEFORE_GC, 165 MEMORY_USAGE_AFTER_GC, 166 }; 167 168 169 private static MappedMXBeanType memoryUsageMapType; 170 static { 171 try { 172 Method m = GcInfo.class.getMethod("getMemoryUsageBeforeGc"); 173 memoryUsageMapType = 174 MappedMXBeanType.getMappedType(m.getGenericReturnType()); 175 } catch (NoSuchMethodException | OpenDataException e) { 176 // Should never reach here 177 throw new AssertionError(e); 178 } 179 } 180 181 static String[] getBaseGcInfoItemNames() { 182 return baseGcInfoItemNames; 183 } 184 185 private static OpenType[] baseGcInfoItemTypes = null; 186 static synchronized OpenType[] getBaseGcInfoItemTypes() { 187 if (baseGcInfoItemTypes == null) { 188 OpenType<?> memoryUsageOpenType = memoryUsageMapType.getOpenType(); 189 baseGcInfoItemTypes = new OpenType<?>[] { 190 SimpleType.LONG, 191 SimpleType.LONG, 192 SimpleType.LONG, 193 SimpleType.LONG, 194 195 memoryUsageOpenType, 196 memoryUsageOpenType, 197 }; 198 } 199 return baseGcInfoItemTypes; 200 } 201 202 public static long getId(CompositeData cd) { 203 return getLong(cd, ID); 204 } 205 public static long getStartTime(CompositeData cd) { 206 return getLong(cd, START_TIME); 207 } 208 public static long getEndTime(CompositeData cd) { 209 return getLong(cd, END_TIME); 210 } 211 212 public static Map<String, MemoryUsage> 213 getMemoryUsageBeforeGc(CompositeData cd) { 214 try { 215 TabularData td = (TabularData) cd.get(MEMORY_USAGE_BEFORE_GC); 216 return cast(memoryUsageMapType.toJavaTypeData(td)); 217 } catch (InvalidObjectException | OpenDataException e) { 218 // Should never reach here 219 throw new AssertionError(e); 220 } 221 } 222 223 @SuppressWarnings("unchecked") 224 public static Map<String, MemoryUsage> cast(Object x) { 225 return (Map<String, MemoryUsage>) x; 226 } 227 public static Map<String, MemoryUsage> 228 getMemoryUsageAfterGc(CompositeData cd) { 229 try { 230 TabularData td = (TabularData) cd.get(MEMORY_USAGE_AFTER_GC); 231 //return (Map<String,MemoryUsage>) 232 return cast(memoryUsageMapType.toJavaTypeData(td)); 233 } catch (InvalidObjectException | OpenDataException e) { 234 // Should never reach here 235 throw new AssertionError(e); 236 } 237 } 238 239 /** 240 * Returns true if the input CompositeData has the expected 241 * CompositeType (i.e. contain all attributes with expected 242 * names and types). Otherwise, return false. 243 */ 244 public static void validateCompositeData(CompositeData cd) { 245 if (cd == null) { 246 throw new NullPointerException("Null CompositeData"); 247 } 248 249 if (!isTypeMatched(getBaseGcInfoCompositeType(), 250 cd.getCompositeType())) { 251 throw new IllegalArgumentException( 252 "Unexpected composite type for GcInfo"); 253 } 254 } 255 256 // This is only used for validation. 257 private static CompositeType baseGcInfoCompositeType = null; 258 static synchronized CompositeType getBaseGcInfoCompositeType() { 259 if (baseGcInfoCompositeType == null) { 260 try { 261 baseGcInfoCompositeType = 262 new CompositeType("sun.management.BaseGcInfoCompositeType", 263 "CompositeType for Base GcInfo", 264 getBaseGcInfoItemNames(), 265 getBaseGcInfoItemNames(), 266 getBaseGcInfoItemTypes()); 267 } catch (OpenDataException e) { 268 // shouldn't reach here 269 throw Util.newException(e); 270 } 271 } 272 return baseGcInfoCompositeType; 273 } 274 275 private static final long serialVersionUID = -5716428894085882742L; 276 }