feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
@@ -0,0 +1,616 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.jvmstat.perfdata.monitor.v2_0;
|
||||
|
||||
import sun.jvmstat.monitor.*;
|
||||
import sun.jvmstat.perfdata.monitor.*;
|
||||
import java.util.*;
|
||||
import java.util.regex.*;
|
||||
import java.nio.*;
|
||||
|
||||
/**
|
||||
* The concrete implementation of version 2.0 of the HotSpot PerfData
|
||||
* Instrumentation buffer. This class is responsible for parsing the
|
||||
* instrumentation memory and constructing the necessary objects to
|
||||
* represent and access the instrumentation objects contained in the
|
||||
* memory buffer.
|
||||
* <p>
|
||||
* The structure of the 2.0 entry is defined in struct PerfDataEnry
|
||||
* as decsribed in perfMemory.hpp. This structure looks like:
|
||||
* <pre>
|
||||
* typedef struct {
|
||||
* jint entry_length; // entry length in bytes
|
||||
* jint name_offset; // offset to entry name, relative to start
|
||||
* // of entry
|
||||
* jint vector_length; // length of the vector. If 0, then scalar.
|
||||
* jbyte data_type; // JNI field descriptor type
|
||||
* jbyte flags; // miscellaneous attribute flags
|
||||
* // 0x01 - supported
|
||||
* jbyte data_units; // unit of measure attribute
|
||||
* jbyte data_variability; // variability attribute
|
||||
* jbyte data_offset; // offset to data item, relative to start
|
||||
* // of entry.
|
||||
* } PerfDataEntry;
|
||||
* </pre>
|
||||
*
|
||||
* @author Brian Doherty
|
||||
* @since 1.5
|
||||
* @see AbstractPerfDataBuffer
|
||||
*/
|
||||
public class PerfDataBuffer extends PerfDataBufferImpl {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
private static final int syncWaitMs =
|
||||
Integer.getInteger("sun.jvmstat.perdata.syncWaitMs", 5000);
|
||||
private static final ArrayList EMPTY_LIST = new ArrayList(0);
|
||||
|
||||
/*
|
||||
* These are primarily for documentary purposes and the match up
|
||||
* with the PerfDataEntry structure in perfMemory.hpp. They are
|
||||
* generally unused in this code, but they are kept consistent with
|
||||
* the data structure just in case some unforseen need arrises.
|
||||
*/
|
||||
private final static int PERFDATA_ENTRYLENGTH_OFFSET=0;
|
||||
private final static int PERFDATA_ENTRYLENGTH_SIZE=4; // sizeof(int)
|
||||
private final static int PERFDATA_NAMEOFFSET_OFFSET=4;
|
||||
private final static int PERFDATA_NAMEOFFSET_SIZE=4; // sizeof(int)
|
||||
private final static int PERFDATA_VECTORLENGTH_OFFSET=8;
|
||||
private final static int PERFDATA_VECTORLENGTH_SIZE=4; // sizeof(int)
|
||||
private final static int PERFDATA_DATATYPE_OFFSET=12;
|
||||
private final static int PERFDATA_DATATYPE_SIZE=1; // sizeof(byte)
|
||||
private final static int PERFDATA_FLAGS_OFFSET=13;
|
||||
private final static int PERFDATA_FLAGS_SIZE=1; // sizeof(byte)
|
||||
private final static int PERFDATA_DATAUNITS_OFFSET=14;
|
||||
private final static int PERFDATA_DATAUNITS_SIZE=1; // sizeof(byte)
|
||||
private final static int PERFDATA_DATAVAR_OFFSET=15;
|
||||
private final static int PERFDATA_DATAVAR_SIZE=1; // sizeof(byte)
|
||||
private final static int PERFDATA_DATAOFFSET_OFFSET=16;
|
||||
private final static int PERFDATA_DATAOFFSET_SIZE=4; // sizeof(int)
|
||||
|
||||
PerfDataBufferPrologue prologue;
|
||||
int nextEntry;
|
||||
long lastNumEntries;
|
||||
IntegerMonitor overflow;
|
||||
ArrayList<Monitor> insertedMonitors;
|
||||
|
||||
/**
|
||||
* Construct a PerfDataBuffer instance.
|
||||
* <p>
|
||||
* This class is dynamically loaded by
|
||||
* {@link AbstractPerfDataBuffer#createPerfDataBuffer}, and this
|
||||
* constructor is called to instantiate the instance.
|
||||
*
|
||||
* @param buffer the buffer containing the instrumentation data
|
||||
* @param lvmid the Local Java Virtual Machine Identifier for this
|
||||
* instrumentation buffer.
|
||||
*/
|
||||
public PerfDataBuffer(ByteBuffer buffer, int lvmid)
|
||||
throws MonitorException {
|
||||
super(buffer, lvmid);
|
||||
prologue = new PerfDataBufferPrologue(buffer);
|
||||
this.buffer.order(prologue.getByteOrder());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected void buildMonitorMap(Map<String, Monitor> map) throws MonitorException {
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
// start at the beginning of the buffer
|
||||
buffer.rewind();
|
||||
|
||||
// create pseudo monitors
|
||||
buildPseudoMonitors(map);
|
||||
|
||||
// wait for the target JVM to indicate that it's intrumentation
|
||||
// buffer is safely accessible
|
||||
synchWithTarget();
|
||||
|
||||
// parse the currently defined entries starting at the first entry.
|
||||
nextEntry = prologue.getEntryOffset();
|
||||
|
||||
// record the number of entries before parsing the structure
|
||||
int numEntries = prologue.getNumEntries();
|
||||
|
||||
// start parsing
|
||||
Monitor monitor = getNextMonitorEntry();
|
||||
while (monitor != null) {
|
||||
map.put(monitor.getName(), monitor);
|
||||
monitor = getNextMonitorEntry();
|
||||
}
|
||||
|
||||
/*
|
||||
* keep track of the current number of entries in the shared
|
||||
* memory for new entry detection purposes. It's possible for
|
||||
* the data structure to be modified while the Map is being
|
||||
* built and the entry count in the header might change while
|
||||
* we are parsing it. The map will contain all the counters
|
||||
* found, but the number recorded in numEntries might be small
|
||||
* than what than the number we actually parsed (due to asynchronous
|
||||
* updates). This discrepency is handled by ignoring any re-parsed
|
||||
* entries when updating the Map in getNewMonitors().
|
||||
*/
|
||||
lastNumEntries = numEntries;
|
||||
|
||||
// keep track of the monitors just added.
|
||||
insertedMonitors = new ArrayList<Monitor>(map.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected void getNewMonitors(Map<String, Monitor> map) throws MonitorException {
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
int numEntries = prologue.getNumEntries();
|
||||
|
||||
if (numEntries > lastNumEntries) {
|
||||
lastNumEntries = numEntries;
|
||||
Monitor monitor = getNextMonitorEntry();
|
||||
|
||||
while (monitor != null) {
|
||||
String name = monitor.getName();
|
||||
|
||||
// guard against re-parsed entries
|
||||
if (!map.containsKey(name)) {
|
||||
map.put(name, monitor);
|
||||
if (insertedMonitors != null) {
|
||||
insertedMonitors.add(monitor);
|
||||
}
|
||||
}
|
||||
monitor = getNextMonitorEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected MonitorStatus getMonitorStatus(Map<String, Monitor> map) throws MonitorException {
|
||||
assert Thread.holdsLock(this);
|
||||
assert insertedMonitors != null;
|
||||
|
||||
// load any new monitors
|
||||
getNewMonitors(map);
|
||||
|
||||
// current implementation doesn't support deletion of reuse of entries
|
||||
ArrayList removed = EMPTY_LIST;
|
||||
ArrayList inserted = insertedMonitors;
|
||||
|
||||
insertedMonitors = new ArrayList<Monitor>();
|
||||
return new MonitorStatus(inserted, removed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the pseudo monitors used to map the prolog data into counters.
|
||||
*/
|
||||
protected void buildPseudoMonitors(Map<String, Monitor> map) {
|
||||
Monitor monitor = null;
|
||||
String name = null;
|
||||
IntBuffer ib = null;
|
||||
|
||||
name = PerfDataBufferPrologue.PERFDATA_MAJOR_NAME;
|
||||
ib = prologue.majorVersionBuffer();
|
||||
monitor = new PerfIntegerMonitor(name, Units.NONE,
|
||||
Variability.CONSTANT, false, ib);
|
||||
map.put(name, monitor);
|
||||
|
||||
name = PerfDataBufferPrologue.PERFDATA_MINOR_NAME;
|
||||
ib = prologue.minorVersionBuffer();
|
||||
monitor = new PerfIntegerMonitor(name, Units.NONE,
|
||||
Variability.CONSTANT, false, ib);
|
||||
map.put(name, monitor);
|
||||
|
||||
name = PerfDataBufferPrologue.PERFDATA_BUFFER_SIZE_NAME;
|
||||
ib = prologue.sizeBuffer();
|
||||
monitor = new PerfIntegerMonitor(name, Units.BYTES,
|
||||
Variability.MONOTONIC, false, ib);
|
||||
map.put(name, monitor);
|
||||
|
||||
name = PerfDataBufferPrologue.PERFDATA_BUFFER_USED_NAME;
|
||||
ib = prologue.usedBuffer();
|
||||
monitor = new PerfIntegerMonitor(name, Units.BYTES,
|
||||
Variability.MONOTONIC, false, ib);
|
||||
map.put(name, monitor);
|
||||
|
||||
name = PerfDataBufferPrologue.PERFDATA_OVERFLOW_NAME;
|
||||
ib = prologue.overflowBuffer();
|
||||
monitor = new PerfIntegerMonitor(name, Units.BYTES,
|
||||
Variability.MONOTONIC, false, ib);
|
||||
map.put(name, monitor);
|
||||
this.overflow = (IntegerMonitor)monitor;
|
||||
|
||||
name = PerfDataBufferPrologue.PERFDATA_MODTIMESTAMP_NAME;
|
||||
LongBuffer lb = prologue.modificationTimeStampBuffer();
|
||||
monitor = new PerfLongMonitor(name, Units.TICKS,
|
||||
Variability.MONOTONIC, false, lb);
|
||||
map.put(name, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that waits until the target jvm indicates that
|
||||
* its shared memory is safe to access.
|
||||
*/
|
||||
protected void synchWithTarget() throws MonitorException {
|
||||
/*
|
||||
* synch must happen with syncWaitMs from now. Default is 5 seconds,
|
||||
* which is reasonabally generous and should provide for extreme
|
||||
* situations like startup delays due to allocation of large ISM heaps.
|
||||
*/
|
||||
long timeLimit = System.currentTimeMillis() + syncWaitMs;
|
||||
|
||||
// loop waiting for the accessible indicater to be non-zero
|
||||
log("synchWithTarget: " + lvmid + " ");
|
||||
while (!prologue.isAccessible()) {
|
||||
|
||||
log(".");
|
||||
|
||||
// give the target jvm a chance to complete initializatoin
|
||||
try { Thread.sleep(20); } catch (InterruptedException e) { }
|
||||
|
||||
if (System.currentTimeMillis() > timeLimit) {
|
||||
logln("failed: " + lvmid);
|
||||
throw new MonitorException("Could not synchronize with target");
|
||||
}
|
||||
}
|
||||
logln("success: " + lvmid);
|
||||
}
|
||||
|
||||
/**
|
||||
* method to extract the next monitor entry from the instrumentation memory.
|
||||
* assumes that nextEntry is the offset into the byte array
|
||||
* at which to start the search for the next entry. method leaves
|
||||
* next entry pointing to the next entry or to the end of data.
|
||||
*/
|
||||
protected Monitor getNextMonitorEntry() throws MonitorException {
|
||||
Monitor monitor = null;
|
||||
|
||||
// entries are always 4 byte aligned.
|
||||
if ((nextEntry % 4) != 0) {
|
||||
throw new MonitorStructureException(
|
||||
"Misaligned entry index: "
|
||||
+ Integer.toHexString(nextEntry));
|
||||
}
|
||||
|
||||
// protect againt a corrupted shard memory region.
|
||||
if ((nextEntry < 0) || (nextEntry > buffer.limit())) {
|
||||
throw new MonitorStructureException(
|
||||
"Entry index out of bounds: "
|
||||
+ Integer.toHexString(nextEntry)
|
||||
+ ", limit = " + Integer.toHexString(buffer.limit()));
|
||||
}
|
||||
|
||||
// check for end of the buffer
|
||||
if (nextEntry == buffer.limit()) {
|
||||
logln("getNextMonitorEntry():"
|
||||
+ " nextEntry == buffer.limit(): returning");
|
||||
return null;
|
||||
}
|
||||
|
||||
buffer.position(nextEntry);
|
||||
|
||||
int entryStart = buffer.position();
|
||||
int entryLength = buffer.getInt();
|
||||
|
||||
// check for valid entry length
|
||||
if ((entryLength < 0) || (entryLength > buffer.limit())) {
|
||||
throw new MonitorStructureException(
|
||||
"Invalid entry length: entryLength = " + entryLength
|
||||
+ " (0x" + Integer.toHexString(entryLength) + ")");
|
||||
}
|
||||
|
||||
// check if last entry occurs before the eof.
|
||||
if ((entryStart + entryLength) > buffer.limit()) {
|
||||
throw new MonitorStructureException(
|
||||
"Entry extends beyond end of buffer: "
|
||||
+ " entryStart = 0x" + Integer.toHexString(entryStart)
|
||||
+ " entryLength = 0x" + Integer.toHexString(entryLength)
|
||||
+ " buffer limit = 0x" + Integer.toHexString(buffer.limit()));
|
||||
}
|
||||
|
||||
if (entryLength == 0) {
|
||||
// end of data
|
||||
return null;
|
||||
}
|
||||
|
||||
// we can safely read this entry
|
||||
int nameOffset = buffer.getInt();
|
||||
int vectorLength = buffer.getInt();
|
||||
byte typeCodeByte = buffer.get();
|
||||
byte flags = buffer.get();
|
||||
byte unitsByte = buffer.get();
|
||||
byte varByte = buffer.get();
|
||||
int dataOffset = buffer.getInt();
|
||||
|
||||
dump_entry_fixed(entryStart, nameOffset, vectorLength, typeCodeByte,
|
||||
flags, unitsByte, varByte, dataOffset);
|
||||
|
||||
// convert common attributes to their object types
|
||||
Units units = Units.toUnits(unitsByte);
|
||||
Variability variability = Variability.toVariability(varByte);
|
||||
TypeCode typeCode = null;
|
||||
boolean supported = (flags & 0x01) != 0;
|
||||
|
||||
try {
|
||||
typeCode = TypeCode.toTypeCode(typeCodeByte);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new MonitorStructureException(
|
||||
"Illegal type code encountered:"
|
||||
+ " entry_offset = 0x" + Integer.toHexString(nextEntry)
|
||||
+ ", type_code = " + Integer.toHexString(typeCodeByte));
|
||||
}
|
||||
|
||||
// verify that the name_offset is contained within the entry bounds
|
||||
if (nameOffset > entryLength) {
|
||||
throw new MonitorStructureException(
|
||||
"Field extends beyond entry bounds"
|
||||
+ " entry_offset = 0x" + Integer.toHexString(nextEntry)
|
||||
+ ", name_offset = 0x" + Integer.toHexString(nameOffset));
|
||||
}
|
||||
|
||||
// verify that the data_offset is contained within the entry bounds
|
||||
if (dataOffset > entryLength) {
|
||||
throw new MonitorStructureException(
|
||||
"Field extends beyond entry bounds:"
|
||||
+ " entry_offset = 0x" + Integer.toHexString(nextEntry)
|
||||
+ ", data_offset = 0x" + Integer.toHexString(dataOffset));
|
||||
}
|
||||
|
||||
// validate the variability and units fields
|
||||
if (variability == Variability.INVALID) {
|
||||
throw new MonitorDataException(
|
||||
"Invalid variability attribute:"
|
||||
+ " entry_offset = 0x" + Integer.toHexString(nextEntry)
|
||||
+ ", variability = 0x" + Integer.toHexString(varByte));
|
||||
}
|
||||
|
||||
if (units == Units.INVALID) {
|
||||
throw new MonitorDataException(
|
||||
"Invalid units attribute: entry_offset = 0x"
|
||||
+ Integer.toHexString(nextEntry)
|
||||
+ ", units = 0x" + Integer.toHexString(unitsByte));
|
||||
}
|
||||
|
||||
// the entry looks good - parse the variable length components
|
||||
|
||||
/*
|
||||
* The name starts at nameOffset and continues up to the first null
|
||||
* byte. however, we don't know the length, but we can approximate it
|
||||
* without searching for the null by using the offset for the data
|
||||
* field, which follows the name field.
|
||||
*/
|
||||
assert (buffer.position() == (entryStart + nameOffset));
|
||||
assert (dataOffset > nameOffset);
|
||||
|
||||
// include possible pad space
|
||||
int maxNameLength = dataOffset-nameOffset;
|
||||
|
||||
// maxNameLength better be less than the total entry length
|
||||
assert (maxNameLength < entryLength);
|
||||
|
||||
// collect the characters, but do not collect the null byte,
|
||||
// as the String(byte[]) constructor does not ignore it!
|
||||
byte[] nameBytes = new byte[maxNameLength];
|
||||
int nameLength = 0;
|
||||
byte b;
|
||||
while (((b = buffer.get()) != 0) && (nameLength < maxNameLength)) {
|
||||
nameBytes[nameLength++] = b;
|
||||
}
|
||||
|
||||
assert (nameLength < maxNameLength);
|
||||
|
||||
// we should before or at the start of the data field
|
||||
assert (buffer.position() <= (entryStart + dataOffset));
|
||||
|
||||
// convert the name bytes into a String
|
||||
String name = new String(nameBytes, 0, nameLength);
|
||||
|
||||
/*
|
||||
* compute the size of the data item - this includes pad
|
||||
* characters used to align the next entry.
|
||||
*/
|
||||
int dataSize = entryLength - dataOffset;
|
||||
|
||||
// set the position to the start of the data item
|
||||
buffer.position(entryStart + dataOffset);
|
||||
|
||||
dump_entry_variable(name, buffer, dataSize);
|
||||
|
||||
if (vectorLength == 0) {
|
||||
// create a scalar Monitor object
|
||||
if (typeCode == TypeCode.LONG) {
|
||||
LongBuffer lb = buffer.asLongBuffer();
|
||||
lb.limit(1); // limit buffer size to one long value.
|
||||
monitor = new PerfLongMonitor(name, units, variability,
|
||||
supported, lb);
|
||||
} else {
|
||||
/*
|
||||
* unexpected type code - coding error or uncoordinated
|
||||
* JVM change
|
||||
*/
|
||||
throw new MonitorTypeException(
|
||||
"Unexpected type code encountered:"
|
||||
+ " entry_offset = 0x" + Integer.toHexString(nextEntry)
|
||||
+ ", name = " + name
|
||||
+ ", type_code = " + typeCode
|
||||
+ " (0x" + Integer.toHexString(typeCodeByte) + ")");
|
||||
}
|
||||
} else {
|
||||
// create a vector Monitor object
|
||||
if (typeCode == TypeCode.BYTE) {
|
||||
if (units != Units.STRING) {
|
||||
// only byte arrays of type STRING are currently supported
|
||||
throw new MonitorTypeException(
|
||||
"Unexpected vector type encounterd:"
|
||||
+ " entry_offset = "
|
||||
+ Integer.toHexString(nextEntry)
|
||||
+ ", name = " + name
|
||||
+ ", type_code = " + typeCode + " (0x"
|
||||
+ Integer.toHexString(typeCodeByte) + ")"
|
||||
+ ", units = " + units + " (0x"
|
||||
+ Integer.toHexString(unitsByte) + ")");
|
||||
}
|
||||
|
||||
ByteBuffer bb = buffer.slice();
|
||||
bb.limit(vectorLength); // limit buffer length to # of chars
|
||||
|
||||
if (variability == Variability.CONSTANT) {
|
||||
monitor = new PerfStringConstantMonitor(name, supported,
|
||||
bb);
|
||||
} else if (variability == Variability.VARIABLE) {
|
||||
monitor = new PerfStringVariableMonitor(name, supported,
|
||||
bb, vectorLength-1);
|
||||
} else if (variability == Variability.MONOTONIC) {
|
||||
// Monotonically increasing byte arrays are not supported
|
||||
throw new MonitorDataException(
|
||||
"Unexpected variability attribute:"
|
||||
+ " entry_offset = 0x"
|
||||
+ Integer.toHexString(nextEntry)
|
||||
+ " name = " + name
|
||||
+ ", variability = " + variability + " (0x"
|
||||
+ Integer.toHexString(varByte) + ")");
|
||||
} else {
|
||||
// variability was validated above, so this unexpected
|
||||
assert false;
|
||||
}
|
||||
} else {
|
||||
// coding error or uncoordinated JVM change
|
||||
throw new MonitorTypeException(
|
||||
"Unexpected type code encountered:"
|
||||
+ " entry_offset = 0x"
|
||||
+ Integer.toHexString(nextEntry)
|
||||
+ ", name = " + name
|
||||
+ ", type_code = " + typeCode + " (0x"
|
||||
+ Integer.toHexString(typeCodeByte) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
// setup index to next entry for next iteration of the loop.
|
||||
nextEntry = entryStart + entryLength;
|
||||
return monitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to dump debugging information
|
||||
*/
|
||||
private void dumpAll(Map<String, Monitor> map, int lvmid) {
|
||||
if (DEBUG) {
|
||||
Set<String> keys = map.keySet();
|
||||
|
||||
System.err.println("Dump for " + lvmid);
|
||||
int j = 0;
|
||||
for (Iterator i = keys.iterator(); i.hasNext(); j++) {
|
||||
Monitor monitor = map.get(i.next());
|
||||
System.err.println(j + "\t" + monitor.getName()
|
||||
+ "=" + monitor.getValue());
|
||||
}
|
||||
System.err.println("nextEntry = " + nextEntry);
|
||||
System.err.println("Buffer info:");
|
||||
System.err.println("buffer = " + buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to dump the fixed portion of an entry.
|
||||
*/
|
||||
private void dump_entry_fixed(int entry_start, int nameOffset,
|
||||
int vectorLength, byte typeCodeByte,
|
||||
byte flags, byte unitsByte, byte varByte,
|
||||
int dataOffset) {
|
||||
if (DEBUG) {
|
||||
System.err.println("Entry at offset: 0x"
|
||||
+ Integer.toHexString(entry_start));
|
||||
System.err.println("\tname_offset = 0x"
|
||||
+ Integer.toHexString(nameOffset));
|
||||
System.err.println("\tvector_length = 0x"
|
||||
+ Integer.toHexString(vectorLength));
|
||||
System.err.println("\tdata_type = 0x"
|
||||
+ Integer.toHexString(typeCodeByte));
|
||||
System.err.println("\tflags = 0x"
|
||||
+ Integer.toHexString(flags));
|
||||
System.err.println("\tdata_units = 0x"
|
||||
+ Integer.toHexString(unitsByte));
|
||||
System.err.println("\tdata_variability = 0x"
|
||||
+ Integer.toHexString(varByte));
|
||||
System.err.println("\tdata_offset = 0x"
|
||||
+ Integer.toHexString(dataOffset));
|
||||
}
|
||||
}
|
||||
|
||||
private void dump_entry_variable(String name, ByteBuffer bb, int size) {
|
||||
if (DEBUG) {
|
||||
char[] toHex = new char[] { '0', '1', '2', '3',
|
||||
'4', '5', '6', '7',
|
||||
'8', '9', 'a', 'b',
|
||||
'c', 'd', 'e', 'f' };
|
||||
|
||||
ByteBuffer data = bb.slice();
|
||||
data.limit(size);
|
||||
|
||||
System.err.println("\tname = " + name);
|
||||
System.err.println("\tdata = ");
|
||||
|
||||
int count=0;
|
||||
while (data.hasRemaining()) {
|
||||
byte b = data.get();
|
||||
byte high = (byte)((b >> 8) & 0x0f);
|
||||
byte low = (byte)(b & 0x0f);
|
||||
|
||||
if (count % 16 == 0) {
|
||||
System.err.print("\t\t" + Integer.toHexString(count / 16)
|
||||
+ ": ");
|
||||
}
|
||||
|
||||
System.err.print(String.valueOf(toHex[high])
|
||||
+ String.valueOf(toHex[low]));
|
||||
|
||||
count++;
|
||||
if (count % 16 == 0) {
|
||||
System.err.println();
|
||||
} else {
|
||||
System.err.print(" ");
|
||||
}
|
||||
}
|
||||
if (count % 16 != 0) {
|
||||
System.err.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void logln(String s) {
|
||||
if (DEBUG) {
|
||||
System.err.println(s);
|
||||
}
|
||||
}
|
||||
|
||||
private void log(String s) {
|
||||
if (DEBUG) {
|
||||
System.err.print(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.jvmstat.perfdata.monitor.v2_0;
|
||||
|
||||
import sun.jvmstat.monitor.*;
|
||||
import sun.jvmstat.perfdata.monitor.*;
|
||||
import java.nio.*;
|
||||
|
||||
/**
|
||||
* Class representing the 2.0 version of the HotSpot PerfData instrumentation
|
||||
* buffer header.
|
||||
* <p>
|
||||
* The PerfDataBufferPrologue class supports parsing of the version
|
||||
* specific portions of the PerfDataPrologue C structure:
|
||||
* <pre>
|
||||
* typedef struct {
|
||||
* ... // handled by superclass
|
||||
* jint used; // number of PerfData memory bytes used
|
||||
* jint overflow; // number of bytes of overflow
|
||||
* jlong mod_time_stamp; // time stamp of the last structural modification
|
||||
* jint entry_offset; // offset of the first PerfDataEntry
|
||||
* jint num_entries; // number of allocated PerfData entries
|
||||
* } PerfDataPrologue
|
||||
* </pre>
|
||||
*
|
||||
* @author Brian Doherty
|
||||
* @since 1.5
|
||||
*/
|
||||
public class PerfDataBufferPrologue extends AbstractPerfDataBufferPrologue {
|
||||
|
||||
private final static int SUPPORTED_MAJOR_VERSION = 2;
|
||||
private final static int SUPPORTED_MINOR_VERSION = 0;
|
||||
|
||||
/*
|
||||
* the following constants must match the field offsets and sizes
|
||||
* in the PerfDataPrologue structure in perfMemory.hpp. offsets are
|
||||
* relative to the start of the PerfDataPrologue structure.
|
||||
*
|
||||
* note that PERFDATA_PROLOG_ACCESSIBLE_OFFSET redefines
|
||||
* PERFDATA_PROLOG_RESERVEDB1_OFFSET from AbstractPerfDataBufferPrologue.
|
||||
*/
|
||||
final static int PERFDATA_PROLOG_ACCESSIBLE_OFFSET=7;
|
||||
final static int PERFDATA_PROLOG_ACCESSIBLE_SIZE=1; // sizeof(byte)
|
||||
final static int PERFDATA_PROLOG_USED_OFFSET=8;
|
||||
final static int PERFDATA_PROLOG_USED_SIZE=4; // sizeof(int)
|
||||
final static int PERFDATA_PROLOG_OVERFLOW_OFFSET=12;
|
||||
final static int PERFDATA_PROLOG_OVERFLOW_SIZE=4; // sizeof(int)
|
||||
final static int PERFDATA_PROLOG_MODTIMESTAMP_OFFSET=16;
|
||||
final static int PERFDATA_PROLOG_MODTIMESTAMP_SIZE=8; // sizeof(long)
|
||||
final static int PERFDATA_PROLOG_ENTRYOFFSET_OFFSET=24;
|
||||
final static int PERFDATA_PROLOG_ENTRYOFFSET_SIZE=4; // sizeof(int)
|
||||
final static int PERFDATA_PROLOG_NUMENTRIES_OFFSET=28;
|
||||
final static int PERFDATA_PROLOG_NUMENTRIES_SIZE=4; // sizeof(int)
|
||||
|
||||
final static int PERFDATA_PROLOG_SIZE=32; // sizeof(struct PerfDataProlog)
|
||||
|
||||
// names for counters that expose prologue fields
|
||||
final static String PERFDATA_BUFFER_SIZE_NAME = "sun.perfdata.size";
|
||||
final static String PERFDATA_BUFFER_USED_NAME = "sun.perfdata.used";
|
||||
final static String PERFDATA_OVERFLOW_NAME = "sun.perfdata.overflow";
|
||||
final static String PERFDATA_MODTIMESTAMP_NAME = "sun.perfdata.timestamp";
|
||||
final static String PERFDATA_NUMENTRIES_NAME = "sun.perfdata.entries";
|
||||
|
||||
/**
|
||||
* Create an instance of PerfDataBufferPrologue from the given
|
||||
* ByteBuffer object.
|
||||
*
|
||||
* @param byteBuffer the buffer containing the binary header data
|
||||
*/
|
||||
public PerfDataBufferPrologue(ByteBuffer byteBuffer)
|
||||
throws MonitorException {
|
||||
super(byteBuffer);
|
||||
assert ((getMajorVersion() == 2) && (getMinorVersion() == 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean supportsAccessible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isAccessible() {
|
||||
assert supportsAccessible();
|
||||
byteBuffer.position(PERFDATA_PROLOG_ACCESSIBLE_OFFSET);
|
||||
byte value = byteBuffer.get();
|
||||
return value != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the utilization of the instrumentation memory buffer.
|
||||
*
|
||||
* @return int - the utilization of the buffer
|
||||
*/
|
||||
public int getUsed() {
|
||||
byteBuffer.position(PERFDATA_PROLOG_USED_OFFSET);
|
||||
return byteBuffer.getInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of the instrumentation memory buffer.
|
||||
*
|
||||
* @return int - the size of the buffer
|
||||
*/
|
||||
public int getBufferSize() {
|
||||
return byteBuffer.capacity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the buffer overflow amount. This value is non-zero if the
|
||||
* HotSpot JVM has overflowed the instrumentation memory buffer.
|
||||
* The target JVM can be restarted with -XX:PerfDataMemSize=X to
|
||||
* create a larger memory buffer.
|
||||
*
|
||||
* @return int - the size of the buffer
|
||||
*/
|
||||
public int getOverflow() {
|
||||
byteBuffer.position(PERFDATA_PROLOG_OVERFLOW_OFFSET);
|
||||
return byteBuffer.getInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time of last modification for the instrumentation
|
||||
* memory buffer. This method returns the time, as ticks since the
|
||||
* start of the target JVM, of the last structural modification to
|
||||
* the instrumentation buffer. Structural modifications correspond to
|
||||
* the addition or deletion of instrumentation objects. Updates to
|
||||
* counter values are not structural modifications.
|
||||
*/
|
||||
public long getModificationTimeStamp() {
|
||||
byteBuffer.position(PERFDATA_PROLOG_MODTIMESTAMP_OFFSET);
|
||||
return byteBuffer.getLong();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the offset of the first PerfDataEntry.
|
||||
*/
|
||||
public int getEntryOffset() {
|
||||
byteBuffer.position(PERFDATA_PROLOG_ENTRYOFFSET_OFFSET);
|
||||
return byteBuffer.getInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the offset of the first PerfDataEntry.
|
||||
*/
|
||||
public int getNumEntries() {
|
||||
byteBuffer.position(PERFDATA_PROLOG_NUMENTRIES_OFFSET);
|
||||
return byteBuffer.getInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int getSize() {
|
||||
return PERFDATA_PROLOG_SIZE; // sizeof(struct PerfDataProlog)
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an IntBuffer that accesses the used value. This is used
|
||||
* to create a Monitor object for this value.
|
||||
*
|
||||
* @return IntBuffer - a ByteBuffer that accesses the used value
|
||||
* in the instrumentation buffer header.
|
||||
* @see #getUsed()
|
||||
*/
|
||||
IntBuffer usedBuffer() {
|
||||
byteBuffer.position(PERFDATA_PROLOG_USED_OFFSET);
|
||||
IntBuffer ib = byteBuffer.asIntBuffer();
|
||||
ib.limit(1);
|
||||
return ib;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an IntBuffer that accesses the size value. This is used
|
||||
* to create a Monitor object for this value.
|
||||
*
|
||||
* @return IntBuffer - a ByteBuffer that accesses the size value
|
||||
* in the instrumentation buffer header.
|
||||
* @see #getBufferSize()
|
||||
*/
|
||||
IntBuffer sizeBuffer() {
|
||||
IntBuffer ib = IntBuffer.allocate(1);
|
||||
ib.put(byteBuffer.capacity());
|
||||
return ib;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an IntBuffer that accesses the overflow value. This is used
|
||||
* to create a Monitor object for this value.
|
||||
*
|
||||
* @return IntBuffer - a ByteBuffer that accesses the overflow value
|
||||
* in the instrumentation buffer header.
|
||||
* @see #getOverflow()
|
||||
*/
|
||||
IntBuffer overflowBuffer() {
|
||||
byteBuffer.position(PERFDATA_PROLOG_OVERFLOW_OFFSET);
|
||||
IntBuffer ib = byteBuffer.asIntBuffer();
|
||||
ib.limit(1);
|
||||
return ib;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a LongBuffer that accesses the modification timestamp value.
|
||||
* This is used to create a Monitor object for this value.
|
||||
*
|
||||
* @return LongBuffer - a ByteBuffer that accesses the modification time
|
||||
* stamp value in the instrumentation buffer header.
|
||||
* @see #getModificationTimeStamp()
|
||||
*/
|
||||
LongBuffer modificationTimeStampBuffer() {
|
||||
byteBuffer.position(PERFDATA_PROLOG_MODTIMESTAMP_OFFSET);
|
||||
LongBuffer lb = byteBuffer.asLongBuffer();
|
||||
lb.limit(1);
|
||||
return lb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an IntBuffer that accesses the number of entries value.
|
||||
* This is used to create a Monitor object for this value.
|
||||
*
|
||||
* @return LongBuffer - a ByteBuffer that accesses the num_entries
|
||||
* value in the instrumentation buffer header.
|
||||
* @see #getNumEntries()
|
||||
*/
|
||||
IntBuffer numEntriesBuffer() {
|
||||
byteBuffer.position(PERFDATA_PROLOG_NUMENTRIES_OFFSET);
|
||||
IntBuffer ib = byteBuffer.asIntBuffer();
|
||||
ib.limit(1);
|
||||
return ib;
|
||||
}
|
||||
}
|
||||
110
jdkSrc/jdk8/sun/jvmstat/perfdata/monitor/v2_0/TypeCode.java
Normal file
110
jdkSrc/jdk8/sun/jvmstat/perfdata/monitor/v2_0/TypeCode.java
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.jvmstat.perfdata.monitor.v2_0;
|
||||
|
||||
/**
|
||||
* A typesafe enumeration for describing standard Java type codes.
|
||||
*
|
||||
* @author Brian Doherty
|
||||
* @since 1.5
|
||||
*/
|
||||
public class TypeCode {
|
||||
|
||||
private final String name;
|
||||
private final char value;
|
||||
|
||||
public static final TypeCode BOOLEAN = new TypeCode("boolean", 'Z');
|
||||
public static final TypeCode CHAR = new TypeCode("char", 'C');
|
||||
public static final TypeCode FLOAT = new TypeCode("float", 'F');
|
||||
public static final TypeCode DOUBLE = new TypeCode("double", 'D');
|
||||
public static final TypeCode BYTE = new TypeCode("byte", 'B');
|
||||
public static final TypeCode SHORT = new TypeCode("short", 'S');
|
||||
public static final TypeCode INT = new TypeCode("int", 'I');
|
||||
public static final TypeCode LONG = new TypeCode("long", 'J');
|
||||
public static final TypeCode OBJECT = new TypeCode("object", 'L');
|
||||
public static final TypeCode ARRAY = new TypeCode("array", '[');
|
||||
public static final TypeCode VOID = new TypeCode("void", 'V');
|
||||
|
||||
private static TypeCode basicTypes[] = {
|
||||
LONG, BYTE, BOOLEAN, CHAR, FLOAT, DOUBLE,
|
||||
SHORT, INT, OBJECT, ARRAY, VOID
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert enumeration value to a String.
|
||||
*
|
||||
* @return String - the string representation for the enumeration.
|
||||
*/
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert enumeration to its character representation.
|
||||
*
|
||||
* @return int - the integer representation for the enumeration.
|
||||
*/
|
||||
public int toChar() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a character value to its corresponding TypeCode object.
|
||||
*
|
||||
* @param c an character representing a Java TypeCode
|
||||
* @return TypeCode - The TypeCode enumeration object for the given
|
||||
* character.
|
||||
* @throws IllegalArgumentException Thrown if <code>c</code> is not
|
||||
* a valid Java TypeCode.
|
||||
*/
|
||||
public static TypeCode toTypeCode(char c) {
|
||||
for (int j = 0; j < basicTypes.length; j++) {
|
||||
if (basicTypes[j].value == c) {
|
||||
return (basicTypes[j]);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a character value to its corresponding TypeCode object.
|
||||
*
|
||||
* @param b a byte representing a Java TypeCode. This value is
|
||||
* converted into a char and used to find the corresponding
|
||||
* TypeCode.
|
||||
* @return TypeCode - The TypeCode enumeration object for the given byte.
|
||||
* @throws IllegalArgumentException Thrown if <code>v</code> is not
|
||||
* a valid Java TypeCode.
|
||||
*/
|
||||
public static TypeCode toTypeCode(byte b) {
|
||||
return toTypeCode((char)b);
|
||||
}
|
||||
|
||||
private TypeCode(String name, char value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user