1/* 2 * Copyright (c) 2004, 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 26package sun.jvmstat.perfdata.monitor; 27 28import sun.jvmstat.monitor.*; 29import java.nio.ByteOrder; 30import java.nio.ByteBuffer; 31import java.nio.IntBuffer; 32 33/** 34 * Abstraction representing the HotSpot PerfData instrumentation buffer 35 * header. This class represents only the fixed portion of the header. 36 * Version specific classes represent the portion of the header that 37 * may change from release to release. 38 * <p> 39 * The PerfDataBufferProlog class supports parsing of the following 40 * C structure: 41 * <pre> 42 * typedef struct { 43 * jint magic; // magic number - 0xcafec0c0 44 * jbyte byte_order; // byte order of the buffer 45 * jbyte major_version; // major and minor version numbers 46 * jbyte minor_version; 47 * jbyte reserved_byte1; // reserved - see concrete implementations for 48 * // possible definition. 49 * ... // remainder is handled by the subclasses. 50 * } PerfDataPrologue 51 * </pre> 52 * 53 * @author Brian Doherty 54 * @since 1.5 55 */ 56public abstract class AbstractPerfDataBufferPrologue { 57 58 protected ByteBuffer byteBuffer; 59 60 /* 61 * the following constants must match the field offsets and sizes 62 * in the PerfDataPrologue structure in perfMemory.hpp 63 */ 64 final static int PERFDATA_PROLOG_OFFSET=0; 65 final static int PERFDATA_PROLOG_MAGIC_OFFSET=0; 66 final static int PERFDATA_PROLOG_BYTEORDER_OFFSET=4; 67 final static int PERFDATA_PROLOG_BYTEORDER_SIZE=1; // sizeof(byte) 68 final static int PERFDATA_PROLOG_MAJOR_OFFSET=5; 69 final static int PERFDATA_PROLOG_MAJOR_SIZE=1; // sizeof(byte) 70 final static int PERFDATA_PROLOG_MINOR_OFFSET=6; 71 final static int PERFDATA_PROLOG_MINOR_SIZE=1; // sizeof(byte) 72 final static int PERFDATA_PROLOG_RESERVEDB1_OFFSET=7; 73 final static int PERFDATA_PROLOG_RESERVEDB1_SIZE=1; // sizeof(byte) 74 75 final static int PERFDATA_PROLOG_SIZE=8; // sizeof(struct PerfDataProlog) 76 77 // these constants should match their #define counterparts in perfMemory.hpp 78 final static byte PERFDATA_BIG_ENDIAN=0; 79 final static byte PERFDATA_LITTLE_ENDIAN=1; 80 final static int PERFDATA_MAGIC = 0xcafec0c0; 81 82 // names for counters that expose the prolog fields 83 public final static String PERFDATA_MAJOR_NAME = 84 "sun.perfdata.majorVersion"; 85 public final static String PERFDATA_MINOR_NAME = 86 "sun.perfdata.minorVersion"; 87 88 /** 89 * Construct a PerfDataBufferPrologue instance. 90 * 91 * @param byteBuffer buffer containing the instrumentation data 92 */ 93 public AbstractPerfDataBufferPrologue(ByteBuffer byteBuffer) 94 throws MonitorException { 95 this.byteBuffer = byteBuffer.duplicate(); 96 97 // the magic number is always stored in big-endian format 98 if (getMagic() != PERFDATA_MAGIC) { 99 throw new MonitorVersionException( 100 "Bad Magic: " + Integer.toHexString(getMagic())); 101 } 102 103 // set the byte order 104 this.byteBuffer.order(getByteOrder()); 105 } 106 107 /** 108 * Get the magic number. 109 * 110 * @return int - the magic number 111 */ 112 public int getMagic() { 113 // the magic number is always stored in big-endian format 114 ByteOrder order = byteBuffer.order(); 115 byteBuffer.order(ByteOrder.BIG_ENDIAN); 116 117 // get the magic number 118 byteBuffer.position(PERFDATA_PROLOG_MAGIC_OFFSET); 119 int magic = byteBuffer.getInt(); 120 121 // restore the byte order 122 byteBuffer.order(order); 123 return magic; 124 } 125 126 /** 127 * Get the byte order. 128 * 129 * @return int - the byte order of the instrumentation buffer 130 */ 131 public ByteOrder getByteOrder() { 132 // byte order field is byte order independent 133 byteBuffer.position(PERFDATA_PROLOG_BYTEORDER_OFFSET); 134 135 byte byte_order = byteBuffer.get(); 136 137 if (byte_order == PERFDATA_BIG_ENDIAN) { 138 return ByteOrder.BIG_ENDIAN; 139 } else { 140 return ByteOrder.LITTLE_ENDIAN; 141 } 142 } 143 144 /** 145 * Get the major version. 146 * 147 * @return int - the major version 148 */ 149 public int getMajorVersion() { 150 // major version field is byte order independent 151 byteBuffer.position(PERFDATA_PROLOG_MAJOR_OFFSET); 152 return (int)byteBuffer.get(); 153 } 154 155 /** 156 * Get the minor version. 157 * 158 * @return int - the minor version 159 */ 160 public int getMinorVersion() { 161 // minor version field is byte order independent 162 byteBuffer.position(PERFDATA_PROLOG_MINOR_OFFSET); 163 return (int)byteBuffer.get(); 164 } 165 166 /** 167 * Get the accessible flag. If supported, it indicates that the shared 168 * memory region is sufficiently initialized for client acccess. 169 * 170 * @return boolean - the initialized status 171 * @see #supportsAccessible() 172 */ 173 public abstract boolean isAccessible(); 174 175 /** 176 * Test if the accessible flag is supported by this version of 177 * the PerfDataBufferPrologue. Although not an abstract method, this 178 * method should be overridden by version specific subclasses. 179 * 180 * @return boolean - the initialized flag support status. 181 * @see #isAccessible() 182 */ 183 public abstract boolean supportsAccessible(); 184 185 /** 186 * Get the size of the header portion of the instrumentation buffer. 187 * 188 * @return int - the size of the header 189 */ 190 public int getSize() { 191 return PERFDATA_PROLOG_SIZE; // sizeof(struct PerfDataProlog) 192 } 193 194 /** 195 * Return an IntBuffer that accesses the major version number. 196 * This is used to create a Monitor object for this value. 197 * 198 * @return IntBuffer - a ByteBuffer that accesses the major version number 199 * in the instrumentation buffer header. 200 */ 201 public IntBuffer majorVersionBuffer() { 202 int[] holder = new int[1]; 203 holder[0] = getMajorVersion(); 204 IntBuffer ib = IntBuffer.wrap(holder); 205 ib.limit(1); 206 return ib; 207 } 208 209 /** 210 * Return an IntBuffer that accesses the minor version number. 211 * This is used to create a Monitor object for this value. 212 * 213 * @return IntBuffer - a ByteBuffer that accesses the minor version number 214 * in the instrumentation buffer header. 215 */ 216 public IntBuffer minorVersionBuffer() { 217 int[] holder = new int[1]; 218 holder[0] = getMinorVersion(); 219 IntBuffer ib = IntBuffer.wrap(holder); 220 ib.limit(1); 221 return ib; 222 } 223 224 /** 225 * Get the magic number from the given byteBuffer. 226 * 227 * @return int - the magic number 228 */ 229 public static int getMagic(ByteBuffer bb) { 230 // save buffer state 231 int position = bb.position(); 232 ByteOrder order = bb.order(); 233 234 // the magic number is always stored in big-endian format 235 bb.order(ByteOrder.BIG_ENDIAN); 236 bb.position(PERFDATA_PROLOG_MAGIC_OFFSET); 237 int magic = bb.getInt(); 238 239 // restore buffer state. 240 bb.order(order); 241 bb.position(position); 242 243 return magic; 244 } 245 246 /** 247 * Get the major version number from the given ByteBuffer. 248 * 249 * @return int - the major version 250 */ 251 public static int getMajorVersion(ByteBuffer bb) { 252 // save buffer state 253 int position = bb.position(); 254 255 bb.position(PERFDATA_PROLOG_MAJOR_OFFSET); 256 int major = (int) bb.get(); 257 258 // restore buffer state. 259 bb.position(position); 260 261 return major; 262 } 263 264 /** 265 * Get the minor version number from the given ByteBuffer. 266 * 267 * @return int - the minor version 268 */ 269 public static int getMinorVersion(ByteBuffer bb) { 270 // save buffer state 271 int position = bb.position(); 272 273 bb.position(PERFDATA_PROLOG_MINOR_OFFSET); 274 int minor = (int)bb.get(); 275 276 // restore buffer state. 277 bb.position(position); 278 279 return minor; 280 } 281 282 /** 283 * Get the byte order for the given ByteBuffer. 284 * 285 * @return int - the byte order of the instrumentation buffer 286 */ 287 public static ByteOrder getByteOrder(ByteBuffer bb) { 288 // save buffer state 289 int position = bb.position(); 290 291 bb.position(PERFDATA_PROLOG_BYTEORDER_OFFSET); 292 ByteOrder order = (bb.get() == PERFDATA_BIG_ENDIAN) 293 ? ByteOrder.BIG_ENDIAN 294 : ByteOrder.LITTLE_ENDIAN; 295 296 // restore buffer state. 297 bb.position(position); 298 return order; 299 } 300} 301