feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,193 @@
/*
* 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;
import java.util.List;
import java.lang.reflect.*;
import java.io.*;
import sun.jvmstat.monitor.*;
import sun.jvmstat.monitor.remote.*;
import sun.jvmstat.monitor.event.VmListener;
/**
* Base class for all MonitoredVm implementations that utilize the
* HotSpot PerfData instrumentation buffer as the communications
* mechanism to the target Java Virtual Machine.
*
* @author Brian Doherty
* @since 1.5
*/
public abstract class AbstractMonitoredVm implements BufferedMonitoredVm {
/**
* The VmIdentifier for the target.
*/
protected VmIdentifier vmid;
/**
* The shared memory instrumentation buffer for the target.
*/
protected AbstractPerfDataBuffer pdb;
/**
* The sampling interval, if the instrumentation buffer is acquired
* by sampling instead of shared memory mechanisms.
*/
protected int interval;
/**
* Create an AbstractMonitoredVm instance.
*
* @param vmid the VmIdentifier for the target
* @param interval the initial sampling interval
*/
public AbstractMonitoredVm(VmIdentifier vmid, int interval)
throws MonitorException {
this.vmid = vmid;
this.interval = interval;
}
/**
* {@inheritDoc}
*/
public VmIdentifier getVmIdentifier() {
return vmid;
}
/**
* {@inheritDoc}
*/
public Monitor findByName(String name) throws MonitorException {
return pdb.findByName(name);
}
/**
* {@inheritDoc}
*/
public List<Monitor> findByPattern(String patternString) throws MonitorException {
return pdb.findByPattern(patternString);
}
/**
* {@inheritDoc}
*/
public void detach() {
/*
* no default action required because the detach operation for the
* native byte buffer is managed by the sun.misc.Perf class.
*/
}
/* ---- Methods to support polled MonitoredVm Implementations ----- */
/**
* {@inheritDoc}
*/
public void setInterval(int interval) {
this.interval = interval;
}
/**
* {@inheritDoc}
*/
public int getInterval() {
return interval;
}
/**
* {@inheritDoc}
*/
public void setLastException(Exception e) {
// XXX: implement
}
/**
* {@inheritDoc}
*/
public Exception getLastException() {
// XXX: implement
return null;
}
/**
* {@inheritDoc}
*/
public void clearLastException() {
// XXX: implement
}
/**
* {@inheritDoc}
*/
public boolean isErrored() {
// XXX: implement
return false;
}
/**
* Get a list of the inserted and removed monitors since last called.
*
* @return MonitorStatus - the status of available Monitors for the
* target Java Virtual Machine.
* @throws MonitorException Thrown if communications errors occur
* while communicating with the target.
*/
public MonitorStatus getMonitorStatus() throws MonitorException {
return pdb.getMonitorStatus();
}
/* --------------- Methods to support VmListeners ----------------- */
/**
* {@inheritDoc}
*/
public abstract void addVmListener(VmListener l);
/**
* {@inheritDoc}
*/
public abstract void removeVmListener(VmListener l);
/* ---- Methods to support BufferedMonitoredVm Implementations ---- */
/**
* {@inheritDoc}
*/
public byte[] getBytes() {
return pdb.getBytes();
}
/**
* {@inheritDoc}
*/
public int getCapacity() {
return pdb.getCapacity();
}
}

View File

@@ -0,0 +1,211 @@
/*
* 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;
import sun.misc.Perf;
import sun.jvmstat.monitor.*;
import java.util.*;
import java.io.*;
import java.lang.reflect.*;
import java.nio.ByteBuffer;
/**
* Abstraction for the HotSpot PerfData instrumentation buffer. This class
* is responsible for acquiring access to the instrumentation buffer for
* a target HotSpot Java Virtual Machine and providing method level access
* to its contents.
*
* @author Brian Doherty
* @since 1.5
*/
public abstract class AbstractPerfDataBuffer {
/**
* Reference to the concrete instance created by the
* {@link #createPerfDataBuffer} method.
*/
protected PerfDataBufferImpl impl;
/**
* Get the Local Java Virtual Machine Identifier, or <em>lvmid</em>
* for the target JVM associated with this instrumentation buffer.
*
* @return int - the lvmid
*/
public int getLocalVmId() {
return impl.getLocalVmId();
}
/**
* Get a copy of the raw instrumentation data.
* This method is used to get a copy of the current bytes in the
* instrumentation buffer. It is generally used for transporting
* those bytes over the network.
*
* @return byte[] - a copy of the bytes in the instrumentation buffer.
*/
public byte[] getBytes() {
return impl.getBytes();
}
/**
* Get the capacity of the instrumentation buffer.
*
* @return int - the capacity, or size, of the instrumentation buffer.
*/
public int getCapacity() {
return impl.getCapacity();
}
/**
* Find a named Instrumentation object.
*
* This method will look for the named instrumentation object in the
* instrumentation exported by this Java Virtual Machine. If an
* instrumentation object with the given name exists, a Monitor interface
* to that object will be return. Otherwise, the method returns
* <tt>null</tt>.
*
* @param name the name of the Instrumentation object to find.
* @return Monitor - the {@link Monitor} object that can be used to
* monitor the the named instrumentation object, or
* <tt>null</tt> if the named object doesn't exist.
* @throws MonitorException Thrown if an error occurs while communicating
* with the target Java Virtual Machine.
*/
public Monitor findByName(String name) throws MonitorException {
return impl.findByName(name);
}
/**
* Find all Instrumentation objects with names matching the given pattern.
*
* This method returns a {@link List} of Monitor objects such that
* the name of each object matches the given pattern.
*
* @param patternString a string containing a pattern as described in
* {@link java.util.regex.Pattern}.
* @return List<Monitor> - a List of {@link Monitor} objects that can be used to
* monitor the instrumentation objects whose names match
* the given pattern. If no instrumentation objects have`
* names matching the given pattern, then an empty List
* is returned.
* @throws MonitorException Thrown if an error occurs while communicating
* with the target Java Virtual Machine.
* @see java.util.regex.Pattern
*/
public List<Monitor> findByPattern(String patternString) throws MonitorException {
return impl.findByPattern(patternString);
}
/**
* Get a list of the inserted and removed monitors since last called.
*
* @return MonitorStatus - the status of available Monitors for the
* target Java Virtual Machine.
* @throws MonitorException Thrown if communications errors occur
* while communicating with the target.
*/
public MonitorStatus getMonitorStatus() throws MonitorException {
return impl.getMonitorStatus();
}
/**
* Get the ByteBuffer containing the instrumentation data.
*
* @return ByteBuffer - a ByteBuffer object that refers to the
* instrumentation data.
*/
public ByteBuffer getByteBuffer() {
return impl.getByteBuffer();
}
/**
* Create the perfdata instrumentation buffer for the given lvmid
* using the given ByteBuffer object as the source of the instrumentation
* data. This method parses the instrumentation buffer header to determine
* key characteristics of the instrumentation buffer and then dynamically
* loads the appropriate class to handle the particular instrumentation
* version.
*
* @param bb the ByteBuffer that references the instrumentation data.
* @param lvmid the Local Java Virtual Machine identifier for this
* instrumentation buffer.
*
* @throws MonitorException
*/
protected void createPerfDataBuffer(ByteBuffer bb, int lvmid)
throws MonitorException {
int majorVersion = AbstractPerfDataBufferPrologue.getMajorVersion(bb);
int minorVersion = AbstractPerfDataBufferPrologue.getMinorVersion(bb);
// instantiate the version specific class
String classname = "sun.jvmstat.perfdata.monitor.v"
+ majorVersion + "_" + minorVersion
+ ".PerfDataBuffer";
try {
Class<?> implClass = Class.forName(classname);
Constructor cons = implClass.getConstructor(new Class[] {
Class.forName("java.nio.ByteBuffer"),
Integer.TYPE
});
impl = (PerfDataBufferImpl)cons.newInstance(new Object[] {
bb, new Integer(lvmid)
});
} catch (ClassNotFoundException e) {
// from Class.forName();
throw new IllegalArgumentException(
"Could not find " + classname + ": " + e.getMessage(), e);
} catch (NoSuchMethodException e) {
// from Class.getConstructor();
throw new IllegalArgumentException(
"Expected constructor missing in " + classname + ": "
+ e.getMessage(), e);
} catch (IllegalAccessException e) {
// from Constructor.newInstance()
throw new IllegalArgumentException(
"Unexpected constructor access in " + classname + ": "
+ e.getMessage(), e);
} catch (InstantiationException e) {
throw new IllegalArgumentException(
classname + "is abstract: " + e.getMessage(), e);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof MonitorException) {
throw (MonitorException)cause;
}
throw new RuntimeException("Unexpected exception: "
+ e.getMessage() , e);
}
}
}

View File

@@ -0,0 +1,300 @@
/*
* 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;
import sun.jvmstat.monitor.*;
import java.nio.ByteOrder;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
/**
* Abstraction representing the HotSpot PerfData instrumentation buffer
* header. This class represents only the fixed portion of the header.
* Version specific classes represent the portion of the header that
* may change from release to release.
* <p>
* The PerfDataBufferProlog class supports parsing of the following
* C structure:
* <pre>
* typedef struct {
* jint magic; // magic number - 0xcafec0c0
* jbyte byte_order; // byte order of the buffer
* jbyte major_version; // major and minor version numbers
* jbyte minor_version;
* jbyte reserved_byte1; // reserved - see concrete implementations for
* // possible definition.
* ... // remainder is handled by the subclasses.
* } PerfDataPrologue
* </pre>
*
* @author Brian Doherty
* @since 1.5
*/
public abstract class AbstractPerfDataBufferPrologue {
protected ByteBuffer byteBuffer;
/*
* the following constants must match the field offsets and sizes
* in the PerfDataPrologue structure in perfMemory.hpp
*/
final static int PERFDATA_PROLOG_OFFSET=0;
final static int PERFDATA_PROLOG_MAGIC_OFFSET=0;
final static int PERFDATA_PROLOG_BYTEORDER_OFFSET=4;
final static int PERFDATA_PROLOG_BYTEORDER_SIZE=1; // sizeof(byte)
final static int PERFDATA_PROLOG_MAJOR_OFFSET=5;
final static int PERFDATA_PROLOG_MAJOR_SIZE=1; // sizeof(byte)
final static int PERFDATA_PROLOG_MINOR_OFFSET=6;
final static int PERFDATA_PROLOG_MINOR_SIZE=1; // sizeof(byte)
final static int PERFDATA_PROLOG_RESERVEDB1_OFFSET=7;
final static int PERFDATA_PROLOG_RESERVEDB1_SIZE=1; // sizeof(byte)
final static int PERFDATA_PROLOG_SIZE=8; // sizeof(struct PerfDataProlog)
// these constants should match their #define counterparts in perfMemory.hpp
final static byte PERFDATA_BIG_ENDIAN=0;
final static byte PERFDATA_LITTLE_ENDIAN=1;
final static int PERFDATA_MAGIC = 0xcafec0c0;
// names for counters that expose the prolog fields
public final static String PERFDATA_MAJOR_NAME =
"sun.perfdata.majorVersion";
public final static String PERFDATA_MINOR_NAME =
"sun.perfdata.minorVersion";
/**
* Construct a PerfDataBufferPrologue instance.
*
* @param byteBuffer buffer containing the instrumentation data
*/
public AbstractPerfDataBufferPrologue(ByteBuffer byteBuffer)
throws MonitorException {
this.byteBuffer = byteBuffer.duplicate();
// the magic number is always stored in big-endian format
if (getMagic() != PERFDATA_MAGIC) {
throw new MonitorVersionException(
"Bad Magic: " + Integer.toHexString(getMagic()));
}
// set the byte order
this.byteBuffer.order(getByteOrder());
}
/**
* Get the magic number.
*
* @return int - the magic number
*/
public int getMagic() {
// the magic number is always stored in big-endian format
ByteOrder order = byteBuffer.order();
byteBuffer.order(ByteOrder.BIG_ENDIAN);
// get the magic number
byteBuffer.position(PERFDATA_PROLOG_MAGIC_OFFSET);
int magic = byteBuffer.getInt();
// restore the byte order
byteBuffer.order(order);
return magic;
}
/**
* Get the byte order.
*
* @return int - the byte order of the instrumentation buffer
*/
public ByteOrder getByteOrder() {
// byte order field is byte order independent
byteBuffer.position(PERFDATA_PROLOG_BYTEORDER_OFFSET);
byte byte_order = byteBuffer.get();
if (byte_order == PERFDATA_BIG_ENDIAN) {
return ByteOrder.BIG_ENDIAN;
} else {
return ByteOrder.LITTLE_ENDIAN;
}
}
/**
* Get the major version.
*
* @return int - the major version
*/
public int getMajorVersion() {
// major version field is byte order independent
byteBuffer.position(PERFDATA_PROLOG_MAJOR_OFFSET);
return (int)byteBuffer.get();
}
/**
* Get the minor version.
*
* @return int - the minor version
*/
public int getMinorVersion() {
// minor version field is byte order independent
byteBuffer.position(PERFDATA_PROLOG_MINOR_OFFSET);
return (int)byteBuffer.get();
}
/**
* Get the accessible flag. If supported, it indicates that the shared
* memory region is sufficiently initialized for client acccess.
*
* @return boolean - the initialized status
* @see #supportsAccessible()
*/
public abstract boolean isAccessible();
/**
* Test if the accessible flag is supported by this version of
* the PerfDataBufferPrologue. Although not an abstract method, this
* method should be overridden by version specific subclasses.
*
* @return boolean - the initialized flag support status.
* @see #isAccessible()
*/
public abstract boolean supportsAccessible();
/**
* Get the size of the header portion of the instrumentation buffer.
*
* @return int - the size of the header
*/
public int getSize() {
return PERFDATA_PROLOG_SIZE; // sizeof(struct PerfDataProlog)
}
/**
* Return an IntBuffer that accesses the major version number.
* This is used to create a Monitor object for this value.
*
* @return IntBuffer - a ByteBuffer that accesses the major version number
* in the instrumentation buffer header.
*/
public IntBuffer majorVersionBuffer() {
int[] holder = new int[1];
holder[0] = getMajorVersion();
IntBuffer ib = IntBuffer.wrap(holder);
ib.limit(1);
return ib;
}
/**
* Return an IntBuffer that accesses the minor version number.
* This is used to create a Monitor object for this value.
*
* @return IntBuffer - a ByteBuffer that accesses the minor version number
* in the instrumentation buffer header.
*/
public IntBuffer minorVersionBuffer() {
int[] holder = new int[1];
holder[0] = getMinorVersion();
IntBuffer ib = IntBuffer.wrap(holder);
ib.limit(1);
return ib;
}
/**
* Get the magic number from the given byteBuffer.
*
* @return int - the magic number
*/
public static int getMagic(ByteBuffer bb) {
// save buffer state
int position = bb.position();
ByteOrder order = bb.order();
// the magic number is always stored in big-endian format
bb.order(ByteOrder.BIG_ENDIAN);
bb.position(PERFDATA_PROLOG_MAGIC_OFFSET);
int magic = bb.getInt();
// restore buffer state.
bb.order(order);
bb.position(position);
return magic;
}
/**
* Get the major version number from the given ByteBuffer.
*
* @return int - the major version
*/
public static int getMajorVersion(ByteBuffer bb) {
// save buffer state
int position = bb.position();
bb.position(PERFDATA_PROLOG_MAJOR_OFFSET);
int major = (int) bb.get();
// restore buffer state.
bb.position(position);
return major;
}
/**
* Get the minor version number from the given ByteBuffer.
*
* @return int - the minor version
*/
public static int getMinorVersion(ByteBuffer bb) {
// save buffer state
int position = bb.position();
bb.position(PERFDATA_PROLOG_MINOR_OFFSET);
int minor = (int)bb.get();
// restore buffer state.
bb.position(position);
return minor;
}
/**
* Get the byte order for the given ByteBuffer.
*
* @return int - the byte order of the instrumentation buffer
*/
public static ByteOrder getByteOrder(ByteBuffer bb) {
// save buffer state
int position = bb.position();
bb.position(PERFDATA_PROLOG_BYTEORDER_OFFSET);
ByteOrder order = (bb.get() == PERFDATA_BIG_ENDIAN)
? ByteOrder.BIG_ENDIAN
: ByteOrder.LITTLE_ENDIAN;
// restore buffer state.
bb.position(position);
return order;
}
}

View File

@@ -0,0 +1,165 @@
/*
* 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;
import java.net.*;
import java.io.*;
import java.util.*;
import java.util.regex.*;
/**
* Class for parsing alias files. File format is expected to follow
* the following syntax:
*
* alias name [alias]*
*
* Java style comments can occur anywhere within the file.
* @author Brian Doherty
* @since 1.5
*/
public class AliasFileParser {
private static final String ALIAS = "alias";
private static final boolean DEBUG = false;
// other variables
private URL inputfile;
private StreamTokenizer st;
private Token currentToken;
AliasFileParser(URL inputfile) {
this.inputfile = inputfile;
}
// value class to hold StreamTokenizer token values
private class Token {
public String sval;
public int ttype;
public Token(int ttype, String sval) {
this.ttype = ttype;
this.sval = sval;
}
}
private void logln(String s) {
if (DEBUG) {
System.err.println(s);
}
}
/**
* method to get the next token as a Token type
*/
private void nextToken() throws IOException {
st.nextToken();
currentToken = new Token(st.ttype, st.sval);
logln("Read token: type = " + currentToken.ttype
+ " string = " + currentToken.sval);
}
/**
* method to match the current Token to a specified token type and
* value Throws a SyntaxException if token doesn't match.
*/
private void match(int ttype, String token)
throws IOException, SyntaxException {
if ((currentToken.ttype == ttype)
&& (currentToken.sval.compareTo(token) == 0)) {
logln("matched type: " + ttype + " and token = "
+ currentToken.sval);
nextToken();
} else {
throw new SyntaxException(st.lineno());
}
}
/*
* method to match the current Token to a specified token type.
* Throws a SyntaxException if token doesn't match.
*/
private void match(int ttype) throws IOException, SyntaxException {
if (currentToken.ttype == ttype) {
logln("matched type: " + ttype + ", token = " + currentToken.sval);
nextToken();
} else {
throw new SyntaxException(st.lineno());
}
}
private void match(String token) throws IOException, SyntaxException {
match(StreamTokenizer.TT_WORD, token);
}
/**
* method to parse the given input file.
*/
public void parse(Map<String, ArrayList<String>> map) throws SyntaxException, IOException {
if (inputfile == null) {
return;
}
BufferedReader r = new BufferedReader(
new InputStreamReader(inputfile.openStream()));
st = new StreamTokenizer(r);
// allow both forms of commenting styles
st.slashSlashComments(true);
st.slashStarComments(true);
st.wordChars('_','_');
nextToken();
while (currentToken.ttype != StreamTokenizer.TT_EOF) {
// look for the start symbol
if ((currentToken.ttype != StreamTokenizer.TT_WORD)
|| (currentToken.sval.compareTo(ALIAS) != 0)) {
nextToken();
continue;
}
match(ALIAS);
String name = currentToken.sval;
match(StreamTokenizer.TT_WORD);
ArrayList<String> aliases = new ArrayList<String>();
do {
aliases.add(currentToken.sval);
match(StreamTokenizer.TT_WORD);
} while ((currentToken.ttype != StreamTokenizer.TT_EOF)
&& (currentToken.sval.compareTo(ALIAS) != 0));
logln("adding map entry for " + name + " values = " + aliases);
map.put(name, aliases);
}
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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;
import java.util.*;
/**
* A TimerTask subclass that keeps a count of the number of executions
* of the task.
*
* @author Brian Doherty
* @since 1.5
*/
public class CountedTimerTask extends TimerTask {
volatile long executionCount;
public long executionCount() {
return executionCount;
}
public void run() {
executionCount++;
}
}

View File

@@ -0,0 +1,87 @@
/*
* 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;
import java.util.*;
/**
* Utility methods for use with {@link CountedTimerTask} instances.
*
* @author Brian Doherty
* @since 1.5
*/
public class CountedTimerTaskUtils {
private static final boolean DEBUG = false;
/**
* Reschedule a CountedTimeTask at a different interval. Probably not
* named correctly. This method cancels the old task and computes the
* delay for starting the new task based on the new interval and the
* time at which the old task was last executed.
*
* @param timer the Timer for the task
* @param oldTask the old Task
* @param newTask the new Task
* @param oldInterval the old interval; use for debugging output
* purposes only.
* @param newInterval scheduling interval in milliseconds
*/
public static void reschedule(Timer timer, CountedTimerTask oldTask,
CountedTimerTask newTask, int oldInterval,
int newInterval) {
long now = System.currentTimeMillis();
long lastRun = oldTask.scheduledExecutionTime();
long expired = now - lastRun;
if (DEBUG) {
System.err.println("computing timer delay: "
+ " oldInterval = " + oldInterval
+ " newInterval = " + newInterval
+ " samples = " + oldTask.executionCount()
+ " expired = " + expired);
}
/*
* check if original task ever ran - if not, then lastRun is
* undefined and we simply set the delay to 0.
*/
long delay = 0;
if (oldTask.executionCount() > 0) {
long remainder = newInterval - expired;
delay = remainder >= 0 ? remainder : 0;
}
if (DEBUG) {
System.err.println("rescheduling sampler task: interval = "
+ newInterval
+ " delay = " + delay);
}
timer.schedule(newTask, delay, newInterval);
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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;
import sun.jvmstat.monitor.MonitorException;
/**
* Exception indicating that improperly formatted data was encountered
* while parsing a HotSpot PerfData buffer.
*
* @author Brian Doherty
* @since 1.5
*/
public class MonitorDataException extends MonitorException {
/**
* Constructs a <code>MonitorDataException</code> with <code>
* null</code> as its error detail message.
*/
public MonitorDataException() {
super();
}
/**
* Constructs an <code>MonitorDataException</code> with the specified
* detail message. The error message string <code>s</code> can later be
* retrieved by the <code>{@link java.lang.Throwable#getMessage}</code>
* method of class <code>java.lang.Throwable</code>.
*
* @param s the detail message.
*/
public MonitorDataException(String s) {
super(s);
}
}

View File

@@ -0,0 +1,77 @@
/*
* 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;
import java.util.List;
/**
* Immutable class containing the list of inserted and deleted
* monitors over an arbitrary time period.
*
* @author Brian Doherty
* @since 1.5
*/
public class MonitorStatus {
/**
* The list of Monitors inserted since the last query.
*/
protected List inserted;
/**
* The list of Monitors removed since the last query.
*/
protected List removed;
/**
* Create a MonitorStatus instance.
*
* @param inserted the list of Monitors inserted
* @param removed the list of Monitors removed
*/
public MonitorStatus(List inserted, List removed) {
this.inserted = inserted;
this.removed = removed;
}
/**
* Get the list of Monitors inserted since the last query.
*
* @return List - the List of Monitor objects inserted or an empty List.
*/
public List getInserted() {
return inserted;
}
/**
* Get the list of Monitors removed since the last query.
*
* @return List - the List of Monitor objects removed or an empty List.
*/
public List getRemoved() {
return removed;
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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;
import sun.jvmstat.monitor.MonitorException;
/**
* Exception indicating that improperly formatted data was encountered
* while parsing a HotSpot PerfData buffer.
*
* @author Brian Doherty
* @since 1.5
*/
public class MonitorStructureException extends MonitorException {
/**
* Constructs a <code>MonitorStructureException</code> with <code>
* null</code> as its error detail message.
*/
public MonitorStructureException() {
super();
}
/**
* Constructs an <code>MonitorStructureException</code> with the specified
* detail message. The error message string <code>s</code> can later be
* retrieved by the <code>{@link java.lang.Throwable#getMessage}</code>
* method of class <code>java.lang.Throwable</code>.
*
* @param s the detail message.
*/
public MonitorStructureException(String s) {
super(s);
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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;
import sun.jvmstat.monitor.MonitorException;
/**
* Exception indicating that an unexpected type was encountered for
* the type field of a PerfData entry in a HotSpot PerfData buffer.
*
* @author Brian Doherty
* @since 1.5
*/
public class MonitorTypeException extends MonitorException {
/**
* Constructs a <code>MonitorTypeException</code> with <code>
* null </code> as its error detail message.
*/
public MonitorTypeException() {
super();
}
/**
* Constructs an <code>MonitorTypeException</code> with the specified
* detail message. The error message string <code>s</code> can later be
* retrieved by the <code>{@link java.lang.Throwable#getMessage}</code>
* method of class <code>java.lang.Throwable</code>.
*
* @param s the detail message.
*/
public MonitorTypeException(String s) {
super(s);
}
}

View File

@@ -0,0 +1,55 @@
/*
* 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;
import sun.jvmstat.monitor.MonitorException;
/**
* Exception thrown when version of the implementation does not
* match the version of the instrumentation exported by a target
* Java Virtual Machine.
*
* @author Brian Doherty
* @since 1.5
*/
public class MonitorVersionException extends MonitorException {
/**
* Create a MonitorVersionException
*/
public MonitorVersionException() {
super();
}
/**
* Create a MonitorVersionException with the given message.
*
* @param message the message to associate with the exception.
*/
public MonitorVersionException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,116 @@
/*
* 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;
import sun.jvmstat.monitor.*;
import java.nio.ByteBuffer;
/**
* Class for monitoring a PerfData Byte Array instrumentation object.
*
* This class is provided to support the PerfStringMonitor classes.
* Instrumentation objects of this direct type currently cannot be
* created or monitored.
*
* @author Brian Doherty
* @since 1.5
* @see sun.jvmstat.instrument.ByteArrayInstrument
*/
public class PerfByteArrayMonitor extends AbstractMonitor
implements ByteArrayMonitor {
/**
* The buffer containing the data for the byte array instrument.
*/
ByteBuffer bb;
/**
* Constructor to create a ByteArrayMonitor for the byte array instrument
* represented by the data in the given buffer.
*
* @param name the name of the instrumentation object
* @param u the units of measure attribute
* @param v the variability attribute
* @param supported support level indicator
* @param bb the buffer containing the byte array instrument data
* @param vectorLength the length of the vector.
*/
public PerfByteArrayMonitor(String name, Units u, Variability v,
boolean supported, ByteBuffer bb,
int vectorLength) {
super(name, u, v, supported, vectorLength);
this.bb = bb;
}
/**
* {@inheritDoc}
* The object returned contains a byte[] with a copy of the current
* elements of the ByteArrayInstrument.
*
* @return Object - a copy of the current value of the elements of the
* byte array instrument. The return type is guaranteed
* to be of type byte[].
*/
public Object getValue() {
return byteArrayValue();
}
/**
* Get a copy of the elements of the byte array instrument.
*
* @return byte[] - a copy of the current value of the elements of the
* byte array instrument.
*/
public byte[] byteArrayValue() {
bb.position(0);
byte[] b = new byte[bb.limit()];
// copy the bytes
bb.get(b);
return b;
}
/**
* Get the current value of an element of the byte array instrument.
*
* @return byte - a copy of the current value of the element at index
* <tt>index</tt> of the byte array instrument.
*/
public byte byteAt(int index) {
bb.position(index);
return bb.get();
}
/**
* Get the maximum length of the byte array for this byte array instrument.
*
* @return int - the maximum length of the byte array.
*/
public int getMaximumLength() {
return bb.limit();
}
}

View File

@@ -0,0 +1,356 @@
/*
* Copyright (c) 2004, 2013, 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;
import sun.jvmstat.monitor.*;
import java.util.*;
import java.nio.*;
import java.io.*;
import java.net.*;
import java.util.regex.*;
/**
* The base classes for the concrete implementations of the HotSpot
* PerfData instrumentation buffer.
*
* @author Brian Doherty
* @since 1.5
* @see AbstractPerfDataBuffer
*/
public abstract class PerfDataBufferImpl {
/**
* The buffer containing the instrumentation data.
*/
protected ByteBuffer buffer;
/**
* A Map of monitor objects found in the instrumentation buffer.
*/
protected Map<String, Monitor> monitors;
/**
* The Local Java Virtual Machine Identifier for this buffer.
*/
protected int lvmid;
/**
* A Map of monitor object names to aliases as read in from the alias map
* file.
*/
protected Map<String, ArrayList<String>> aliasMap;
/**
* A cache of resolved monitor aliases.
*/
protected Map aliasCache;
/**
* Constructor.
*
* @param buffer the ByteBuffer containing the instrumentation data.
* @param lvmid the Local Java Virtual Machine Identifier for this
* instrumentation buffer.
*/
protected PerfDataBufferImpl(ByteBuffer buffer, int lvmid) {
this.buffer = buffer;
this.lvmid = lvmid;
this.monitors = new TreeMap<String, Monitor>();
this.aliasMap = new HashMap<String, ArrayList<String>>();
this.aliasCache = new HashMap();
}
/**
* Get the Local Java Virtual Machine Identifier, or <em>lvmid</em>
* for the target JVM associated with this instrumentation buffer.
*
* @return int - the lvmid
*/
public int getLocalVmId() {
return lvmid;
}
/**
* Get a copy of the raw instrumentation data.
* This method is used to get a copy of the current bytes in the
* instrumentation buffer. It is generally used for transporting
* those bytes over the network.
*
* @return byte[] - a copy of the bytes in the instrumentation buffer.
*/
public byte[] getBytes() {
ByteBuffer bb = null;
synchronized (this) {
/*
* this operation is potentially time consuming, and the result
* is unused when the getBytes() interface is used. However, the
* call is necessary in order to synchronize this monitoring
* client with the target jvm, which assures that the receiver
* of the byte[] gets an image that is initialized to a usable
* state. Otherwise, they might only get a snapshot of an
* empty instrumentation buffer immediately after it was created.
*/
try {
if (monitors.isEmpty()) {
buildMonitorMap(monitors);
}
} catch (MonitorException e) {
/*
* just ignore this here and let the receiver of the
* byte[] detect and handle the problem.
*/
}
bb = buffer.duplicate();
}
bb.rewind();
byte[] bytes = new byte[bb.limit()];
bb.get(bytes);
return bytes;
}
/**
* Get the capacity of the instrumentation buffer.
*
* @return int - the capacity, or size, of the instrumentation buffer.
*/
public int getCapacity() {
return buffer.capacity();
}
/**
* Get the ByteBuffer containing the instrumentation data.
*
* @return ByteBuffer - a ByteBuffer object that refers to the
* instrumentation data.
*/
ByteBuffer getByteBuffer() {
// receiver is responsible for assuring that the buffer's state
// is that of an initialized target.
return buffer;
}
/**
* Build the alias mapping. Uses the default alias map file unless
* the sun.jvmstat.perfdata.aliasmap file indicates some other
* file as the source.
*/
private void buildAliasMap() {
assert Thread.holdsLock(this);
URL aliasURL = null;
String filename = System.getProperty("sun.jvmstat.perfdata.aliasmap");
if (filename != null) {
File f = new File(filename);
try {
aliasURL = f.toURL();
} catch (MalformedURLException e) {
throw new IllegalArgumentException(e);
}
} else {
aliasURL = getClass().getResource(
"/sun/jvmstat/perfdata/resources/aliasmap");
}
assert aliasURL != null;
AliasFileParser aliasParser = new AliasFileParser(aliasURL);
try {
aliasParser.parse(aliasMap);
} catch (IOException e) {
System.err.println("Error processing " + filename + ": "
+ e.getMessage());
} catch (SyntaxException e) {
System.err.println("Syntax error parsing " + filename + ": "
+ e.getMessage());
}
}
/**
* Find the Monitor object for the named counter by using one of its
* aliases.
*/
protected Monitor findByAlias(String name) {
assert Thread.holdsLock(this);
Monitor m = (Monitor)aliasCache.get(name);
if (m == null) {
ArrayList al = aliasMap.get(name);
if (al != null) {
for (Iterator i = al.iterator(); i.hasNext() && m == null; ) {
String alias = (String)i.next();
m = (Monitor)monitors.get(alias);
}
}
}
return m;
}
/**
* Find a named Instrumentation object.
*
* This method will look for the named instrumentation object in the
* instrumentation exported by this Java Virtual Machine. If an
* instrumentation object with the given name exists, a Monitor interface
* to that object will be return. Otherwise, the method returns
* <tt>null</tt>. The method will map requests for instrumention objects
* using old names to their current names, if applicable.
*
*
*
* @param name the name of the Instrumentation object to find.
* @return Monitor - the {@link Monitor} object that can be used to
* monitor the the named instrumentation object, or
* <tt>null</tt> if the named object doesn't exist.
* @throws MonitorException Thrown if an error occurs while communicating
* with the target Java Virtual Machine.
*/
public Monitor findByName(String name) throws MonitorException {
Monitor m = null;
synchronized (this) {
if (monitors.isEmpty()) {
buildMonitorMap(monitors);
buildAliasMap();
}
// look for the requested monitor
m = monitors.get(name);
if (m == null) {
// not found - load any new monitors, and try again.
getNewMonitors(monitors);
m = monitors.get(name);
}
if (m == null) {
// still not found, look for aliases
m = findByAlias(name);
}
}
return m;
}
/**
* Find all Instrumentation objects with names matching the given pattern.
*
* This method returns a {@link List} of Monitor objects such that
* the name of each object matches the given pattern.
*
* @param patternString a string containing a pattern as described in
* {@link java.util.regex.Pattern}.
* @return List<Monitor> - a List of {@link Monitor} objects that can be used to
* monitor the instrumentation objects whose names match
* the given pattern. If no instrumentation objects have`
* names matching the given pattern, then an empty List
* is returned.
* @throws MonitorException Thrown if an error occurs while communicating
* with the target Java Virtual Machine.
* @see java.util.regex.Pattern
*/
public List<Monitor> findByPattern(String patternString)
throws MonitorException, PatternSyntaxException {
synchronized(this) {
if (monitors.isEmpty()) {
buildMonitorMap(monitors);
} else {
getNewMonitors(monitors);
}
}
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher("");
List<Monitor> matches = new ArrayList<Monitor>();
Set monitorSet = monitors.entrySet();
for (Iterator i = monitorSet.iterator(); i.hasNext(); /* empty */) {
Map.Entry me = (Map.Entry)i.next();
String name = (String)me.getKey();
Monitor m = (Monitor)me.getValue();
// apply pattern to monitor item name
matcher.reset(name);
// if the pattern matches, then add monitor to list
if (matcher.lookingAt()) {
matches.add((Monitor)me.getValue());
}
}
return matches;
}
/**
* Get a list of the inserted and removed monitors since last called.
*
* @return MonitorStatus - the status of available Monitors for the
* target Java Virtual Machine.
* @throws MonitorException Thrown if communications errors occur
* while communicating with the target.
*/
public MonitorStatus getMonitorStatus() throws MonitorException {
synchronized(this) {
if (monitors.isEmpty()) {
buildMonitorMap(monitors);
}
return getMonitorStatus(monitors);
}
}
// PerfDataBuffer implementation specific classes
/**
* get the list of inserted and removed monitors since last called.
*
* @param m the map of Monitors.
* @throws MonitorException Thrown if communications errors occur
* while communicating with the target.
*/
protected abstract MonitorStatus getMonitorStatus(Map<String, Monitor> m)
throws MonitorException;
/**
* build the map of Monitor objects.
*
* @param m the map of Monitors.
* @throws MonitorException Thrown if communications errors occur
* while communicating with the target.
*/
protected abstract void buildMonitorMap(Map<String, Monitor> m) throws MonitorException;
/**
* get the new Monitor objects from the Map of Monitor objects.
*
* @param m the map of Monitors.
* @throws MonitorException Thrown if communications errors occur
* while communicating with the target.
*/
protected abstract void getNewMonitors(Map<String, Monitor> m) throws MonitorException;
}

View File

@@ -0,0 +1,81 @@
/*
* 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;
import sun.jvmstat.monitor.*;
import java.nio.IntBuffer;
/**
* Class for monitoring a PerfData Integer instrument.
*
* @author Brian Doherty
* @since 1.5
*/
public class PerfIntegerMonitor extends AbstractMonitor
implements IntegerMonitor {
/**
* The buffer containing the data for the integer instrument.
*/
IntBuffer ib;
/**
* Constructor to create an IntegerMonitor object for the integer
* instrument represented by the data in the given buffer.
*
* @param name the name of the integer instrument
* @param u the units of measure attribute
* @param v the variability attribute
* @param supported support level indicator
* @param ib the buffer containing the integer instrument data.
*/
public PerfIntegerMonitor(String name, Units u, Variability v,
boolean supported, IntBuffer ib) {
super(name, u, v, supported);
this.ib = ib;
}
/**
* {@inheritDoc}
* The object returned contains an Integer object containing the
* current value of the IntegerInstrument.
*
* @return Object - the current value of the the IntegerInstrument. The
* return type is guaranteed to be of type Integer.
*/
public Object getValue() {
return new Integer(ib.get(0));
}
/**
* Return the current value of the IntegerInstrument as an int.
*
* @return int - a the current value of the IntegerInstrument.
*/
public int intValue() {
return ib.get(0);
}
}

View File

@@ -0,0 +1,80 @@
/*
* 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;
import sun.jvmstat.monitor.*;
import java.nio.LongBuffer;
/**
* Class for monitoring a PerfData Long instrument.
*
* @author Brian Doherty
* @since 1.5
*/
public class PerfLongMonitor extends AbstractMonitor implements LongMonitor {
/**
* The buffer containing the data for the long instrument.
*/
LongBuffer lb;
/**
* Constructor to create a LongMonitor object for the long instrument
* represented by the data in the given buffer.
*
* @param name the name of the long instrument
* @param u the units of measure attribute
* @param v the variability attribute
* @param supported support level indicator
* @param lb the buffer containing the long instrument data.
*/
public PerfLongMonitor(String name, Units u, Variability v,
boolean supported, LongBuffer lb) {
super(name, u, v, supported);
this.lb = lb;
}
/**
* {@inheritDoc}
* The object returned contains a Long object containing the
* current value of the LongInstrument.
*
* @return Object - the current value of the the LongInstrument. The
* return type is guaranteed to be of type Long.
*/
public Object getValue() {
return new Long(lb.get(0));
}
/**
* Return the current value of the LongInstrument as an long.
*
* @return long - the current value of the LongInstrument
*/
public long longValue() {
return lb.get(0);
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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;
import sun.jvmstat.monitor.*;
import java.nio.ByteBuffer;
/**
* Class for monitoring a constant PerfData String instrument. The
* value associated with a constant string instrument is fixed at
* the string instrument's creation time. Its value and length never
* change.
*
* @author Brian Doherty
* @since 1.5
*/
public class PerfStringConstantMonitor extends PerfStringMonitor {
/**
* The cached value of the string instrument.
*/
String data;
/**
* Constructor to create a StringMonitor object for the constant string
* instrument object represented by the data in the given buffer.
*
* @param name the name of the instrumentation object
* @param supported support level indicator
* @param bb the buffer containing the string instrument data
*/
public PerfStringConstantMonitor(String name, boolean supported,
ByteBuffer bb) {
super(name, Variability.CONSTANT, supported, bb);
this.data = super.stringValue();
}
/**
* {@inheritDoc}
*/
public Object getValue() {
return data; // return the cached string
}
/**
* {@inheritDoc}
*/
public String stringValue() {
return data; // return the cached string
}
}

View File

@@ -0,0 +1,103 @@
/*
* 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;
import sun.jvmstat.monitor.*;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
/**
* Class for monitoring a PerfData String instrument.
*
* @author Brian Doherty
* @since 1.5
*/
public class PerfStringMonitor extends PerfByteArrayMonitor
implements StringMonitor {
private static Charset defaultCharset = Charset.defaultCharset();
/**
* Constructor to create a StringMonitor object for the string instrument
* represented by the data in the given buffer.
*
* @param name the name of the string instrument
* @param v the variability attribute
* @param supported support level indicator
* @param bb the buffer containing the string instrument data.
*/
public PerfStringMonitor(String name, Variability v, boolean supported,
ByteBuffer bb) {
this(name, v, supported, bb, bb.limit());
}
/**
* Constructor to create a StringMonitor object for the string instrument
* represented by the data in the given buffer.
*
* @param name the name of the string instrument
* @param v the variability attribute
* @param supported support level indicator
* @param bb the buffer containing the string instrument data.
* @param maxLength the maximum length of the string data.
*/
public PerfStringMonitor(String name, Variability v, boolean supported,
ByteBuffer bb, int maxLength) {
super(name, Units.STRING, v, supported, bb, maxLength);
}
/**
* {@inheritDoc}
* The object returned contains a String with a copy of the current
* value of the StringInstrument.
*
* @return Object - a copy of the current value of the StringInstrument.
* The return value is guaranteed to be of type String.
*/
public Object getValue() {
return stringValue();
}
/**
* Return the current value of the StringInstrument as a String.
*
* @return String - a copy of the current value of the StringInstrument.
*/
public String stringValue() {
String str = "";
byte[] b = byteArrayValue();
// catch null strings
if ((b == null) || (b.length <= 1) || (b[0] == (byte)0)) {
return str;
}
int i;
for (i = 0; i < b.length && b[i] != (byte)0; i++);
return new String(b, 0, i, defaultCharset);
}
}

View File

@@ -0,0 +1,68 @@
/*
* 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;
import sun.jvmstat.monitor.*;
import java.nio.ByteBuffer;
/**
*
* Class for monitoring a variable PerfData String instrument.
* The current value of a variable string instrument changes over time.
*
* @author Brian Doherty
* @since 1.5
*/
public class PerfStringVariableMonitor extends PerfStringMonitor {
/**
* Constructor to create a StringMonitor object for the variable string
* instrument represented by the data in the given buffer.
*
* @param name the name of the string instrument
* @param supported support level indicator
* @param bb the buffer containing the string instrument data.
*/
public PerfStringVariableMonitor(String name, boolean supported,
ByteBuffer bb) {
this(name, supported, bb, bb.limit());
}
/**
* Constructor to create a StringMonitor object for the variable
* string instrument represented by the data in the given buffer.
*
* @param name the name of the string instrument
* @param bb the buffer containing the string instrument data.
* @param supported support level indicator
* @param maxLength the maximum length of the string data.
*/
public PerfStringVariableMonitor(String name, boolean supported,
ByteBuffer bb, int maxLength) {
// account for the null terminator by adding 1 to maxLength
super(name, Variability.VARIABLE, supported, bb, maxLength+1);
}
}

View File

@@ -0,0 +1,49 @@
/*
* 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;
import java.net.*;
import java.io.*;
import java.util.*;
import java.util.regex.*;
/**
* Class for encapsulating syntax exceptions generated by AliasFileParser.
*
* @author Brian Doherty
* @since 1.5
*/
public class SyntaxException extends Exception {
int lineno;
public SyntaxException(int lineno) {
this.lineno = lineno;
}
public String getMessage() {
return "syntax error at line " + lineno;
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2004, 2013, 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.protocol.file;
import sun.jvmstat.monitor.*;
import sun.jvmstat.monitor.event.VmListener;
import sun.jvmstat.perfdata.monitor.*;
import java.util.List;
import java.lang.reflect.*;
import java.io.*;
/**
* Concrete implementation of the AbstractMonitoredVm class for the
* <em>file:</em> protocol for the HotSpot PerfData monitoring implementation.
* <p>
* This class provides the ability to attach to the instrumentation buffer
* (saved or live) of a target Java Virtual Machine by providing a
* <em>file</em> URI to a file containing the instrmentation buffer data.
*
* @author Brian Doherty
* @since 1.5
*/
public class FileMonitoredVm extends AbstractMonitoredVm {
/**
* Create a FileMonitoredVm instance.
*
* @param vmid the vm identifier referring to the file
* @param interval sampling interval (unused in this protocol).
*/
public FileMonitoredVm(VmIdentifier vmid, int interval)
throws MonitorException {
super(vmid, interval);
this.pdb = new PerfDataBuffer(vmid);
}
/**
* {@inheritDoc}.
*<p>
* Note - the <em>file:</em> protocol currently does not support
* the registration or notification of listeners.
*/
public void addVmListener(VmListener l) { }
/**
* {@inheritDoc}.
*<p>
* Note - the <em>file:</em> protocol currently does not support
* the registration or notification of listeners.
*/
public void removeVmListener(VmListener l) { }
}

View File

@@ -0,0 +1,116 @@
/*
* 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.protocol.file;
import sun.jvmstat.monitor.*;
import sun.jvmstat.monitor.event.HostListener;
import sun.jvmstat.perfdata.monitor.*;
import java.util.*;
import java.net.*;
/**
* Concrete implementation of the MonitoredHost interface for the
* <em>file:</em> protocol of the HotSpot PerfData monitoring implementation.
*
* @author Brian Doherty
* @since 1.5
*/
public class MonitoredHostProvider extends MonitoredHost {
/**
* The default polling interval. Not used by the <em>file:</em> protocol.
*/
public static final int DEFAULT_POLLING_INTERVAL = 0;
/**
* Create a MonitoredHostProvider instance using the given HostIdentifier.
*
* @param hostId the host identifier for this MonitoredHost
*/
public MonitoredHostProvider(HostIdentifier hostId) {
this.hostId = hostId;
}
/**
* {@inheritDoc}
*/
public MonitoredVm getMonitoredVm(VmIdentifier vmid)
throws MonitorException {
return getMonitoredVm(vmid, DEFAULT_POLLING_INTERVAL);
}
/**
* {@inheritDoc}.
* <p>
* Note - the <em>file:</em> protocol silently ignores the
* <tt>interval</tt> parameter.
*/
public MonitoredVm getMonitoredVm(VmIdentifier vmid, int interval)
throws MonitorException {
// don't attempt to resolve 'file:' based vmid
return new FileMonitoredVm(vmid, interval);
}
/**
* {@inheritDoc}
*/
public void detach(MonitoredVm vm) {
vm.detach();
}
/**
* {@inheritDoc}.
* <p>
* Note - the <em>file:</em> protocol currenly does not support
* registration or notification of event listeners. This method
* silently ignores the add request.
*/
public void addHostListener(HostListener listener) {
// no HostListener support for 'file:' based VmIdentifiers
}
/**
* {@inheritDoc}.
* <p>
* Note - the <em>file:</em> protocol currenly does not support
* registration or notification of event listeners. This method
* silently ignores the remove request.
*/
public void removeHostListener(HostListener listener) {
// no HostListener support for 'file:' based VmIdentifiers
}
/**
* {@inheritDoc}.
* <p>
* Note - the <em>file:</em> protocol currently does not support the
* notion of tracking active or inactive Java Virtual Machines. This
* method currently returns an empty set.
*/
public Set<Integer> activeVms() {
return new HashSet<Integer>(0);
}
}

View File

@@ -0,0 +1,80 @@
/*
* 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.protocol.file;
import sun.jvmstat.monitor.*;
import sun.jvmstat.perfdata.monitor.*;
import java.io.*;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* The concrete PerfDataBuffer implementation for the <em>file:</em>
* protocol for the HotSpot PerfData monitoring implemetation.
* <p>
* This class is responsible for acquiring access to the instrumentation
* buffer stored in a file referenced by a file URI.
*
* @author Brian Doherty
* @since 1.5
*/
public class PerfDataBuffer extends AbstractPerfDataBuffer {
/**
* Create a PerfDataBuffer instance for accessing the specified
* instrumentation buffer.
*
* @param vmid the <em>file:</em> URI to the instrumentation buffer file
*
* @throws MonitorException
*/
public PerfDataBuffer(VmIdentifier vmid) throws MonitorException {
File f = new File(vmid.getURI());
String mode = vmid.getMode();
try {
FileChannel fc = new RandomAccessFile(f, mode).getChannel();
ByteBuffer bb = null;
if (mode.compareTo("r") == 0) {
bb = fc.map(FileChannel.MapMode.READ_ONLY, 0L, (int)fc.size());
} else if (mode.compareTo("rw") == 0) {
bb = fc.map(FileChannel.MapMode.READ_WRITE, 0L, (int)fc.size());
} else {
throw new IllegalArgumentException("Invalid mode: " + mode);
}
fc.close(); // doesn't need to remain open
createPerfDataBuffer(bb, 0);
} catch (FileNotFoundException e) {
throw new MonitorException("Could not find " + vmid.toString());
} catch (IOException e) {
throw new MonitorException("Could not read " + vmid.toString());
}
}
}

View File

@@ -0,0 +1,62 @@
/*
* 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.protocol.local;
import sun.jvmstat.monitor.*;
import sun.jvmstat.perfdata.monitor.MonitorStatus;
import java.util.*;
import java.util.regex.*;
import java.io.*;
/**
* Singleton Timer subclass to run polling tasks that generate events
* for local Java Virtual Machines..
*
* @author Brian Doherty
* @since 1.5
*/
public class LocalEventTimer extends Timer {
private static LocalEventTimer instance; // singleton instance
/**
* Creates the singleton LocalEventTimer instance.
*/
private LocalEventTimer() {
super(true);
}
/**
* Get the singleton LocalEventTimer instance
*
* @return LocalEventTimer - the singleton LocalEventTimer instance
*/
public static synchronized LocalEventTimer getInstance() {
if (instance == null) {
instance = new LocalEventTimer();
}
return instance;
}
}

View File

@@ -0,0 +1,213 @@
/*
* Copyright (c) 2004, 2008, 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.protocol.local;
import java.util.*;
import java.lang.reflect.*;
import java.io.*;
import sun.jvmstat.monitor.*;
import sun.jvmstat.monitor.event.*;
import sun.jvmstat.perfdata.monitor.*;
/**
* Concrete implementation of the AbstractMonitoredVm class for the
* <em>local:</em> protocol for the HotSpot PerfData monitoring implementation.
* <p>
* This class provides the ability to attach to the instrumentation buffer
* of a live target Java Virtual Machine through a HotSpot specific attach
* mechanism.
*
* @author Brian Doherty
* @since 1.5
*/
public class LocalMonitoredVm extends AbstractMonitoredVm {
/**
* List of registered listeners.
*/
private ArrayList<VmListener> listeners;
/**
* Task performing listener notification.
*/
private NotifierTask task;
/**
* Create a LocalMonitoredVm instance.
*
* @param vmid the vm identifier specifying the target JVM
* @param interval the sampling interval
*/
public LocalMonitoredVm(VmIdentifier vmid, int interval)
throws MonitorException {
super(vmid, interval);
this.pdb = new PerfDataBuffer(vmid);
listeners = new ArrayList<VmListener>();
}
/**
* {@inheritDoc}.
*/
public void detach() {
if (interval > 0) {
/*
* if the notifier task is running, stop it, otherwise it can
* access non-existent memory once we've detached from the
* underlying buffer.
*/
if (task != null) {
task.cancel();
task = null;
}
}
super.detach();
}
/**
* {@inheritDoc}.
*/
public void addVmListener(VmListener l) {
synchronized(listeners) {
listeners.add(l);
if (task == null) {
task = new NotifierTask();
LocalEventTimer timer = LocalEventTimer.getInstance();
timer.schedule(task, interval, interval);
}
}
}
/**
* {@inheritDoc}.
*/
public void removeVmListener(VmListener l) {
synchronized(listeners) {
listeners.remove(l);
if (listeners.isEmpty() && task != null) {
task.cancel();
task = null;
}
}
}
/**
* {@inheritDoc}.
*/
public void setInterval(int newInterval) {
synchronized(listeners) {
if (newInterval == interval) {
return;
}
int oldInterval = interval;
super.setInterval(newInterval);
if (task != null) {
task.cancel();
NotifierTask oldTask = task;
task = new NotifierTask();
LocalEventTimer timer = LocalEventTimer.getInstance();
CountedTimerTaskUtils.reschedule(timer, oldTask, task,
oldInterval, newInterval);
}
}
}
/**
* Fire MonitoredVmStructureChanged events.
*
* @param inserted List of Monitor objects inserted.
* @param removed List of Monitor objects removed.
*/
void fireMonitorStatusChangedEvents(List inserted, List removed) {
MonitorStatusChangeEvent ev = null;
ArrayList registered = null;
synchronized (listeners) {
registered = (ArrayList)listeners.clone();
}
for (Iterator i = registered.iterator(); i.hasNext(); /* empty */) {
VmListener l = (VmListener)i.next();
// lazily create the event object;
if (ev == null) {
ev = new MonitorStatusChangeEvent(this, inserted, removed);
}
l.monitorStatusChanged(ev);
}
}
/**
* Fire MonitoredUpdated events.
*/
void fireMonitorsUpdatedEvents() {
VmEvent ev = null;
ArrayList<VmListener> registered = null;
synchronized (listeners) {
registered = cast(listeners.clone());
}
for (VmListener l : registered) {
// lazily create the event object;
if (ev == null) {
ev = new VmEvent(this);
}
l.monitorsUpdated(ev);
}
}
/**
* Class to notify listeners of Monitor related events for
* the target JVM.
*/
private class NotifierTask extends CountedTimerTask {
public void run() {
super.run();
try {
MonitorStatus status = getMonitorStatus();
List inserted = status.getInserted();
List removed = status.getRemoved();
if (!inserted.isEmpty() || !removed.isEmpty()) {
fireMonitorStatusChangedEvents(inserted, removed);
}
fireMonitorsUpdatedEvents();
} catch (MonitorException e) {
// XXX: use logging api
System.err.println("Exception updating monitors for "
+ getVmIdentifier());
e.printStackTrace();
}
}
}
// Suppress unchecked cast warning msg.
@SuppressWarnings("unchecked")
static <T> T cast(Object x) {
return (T) x;
}
}

View File

@@ -0,0 +1,198 @@
/*
* Copyright (c) 2004, 2007, 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.protocol.local;
import sun.jvmstat.monitor.*;
import sun.jvmstat.monitor.event.*;
import java.util.*;
import java.util.regex.*;
import java.io.*;
/**
* Class for managing the LocalMonitoredVm instances on the local system.
* <p>
* This class is responsible for the mechanism that detects the active
* HotSpot Java Virtual Machines on the local host and possibly for a
* specific user. The ability to detect all possible HotSpot Java Virtual
* Machines on the local host may be limited by the permissions of the
* principal running this JVM.
*
* @author Brian Doherty
* @since 1.5
*/
public class LocalVmManager {
private String userName; // user name for monitored jvm
private File tmpdir;
private Pattern userPattern;
private Matcher userMatcher;
private FilenameFilter userFilter;
private Pattern filePattern;
private Matcher fileMatcher;
private FilenameFilter fileFilter;
private Pattern tmpFilePattern;
private Matcher tmpFileMatcher;
private FilenameFilter tmpFileFilter;
/**
* Creates a LocalVmManager instance for the local system.
* <p>
* Manages LocalMonitoredVm instances for which the principal
* has appropriate permissions.
*/
public LocalVmManager() {
this(null);
}
/**
* Creates a LocalVmManager instance for the given user.
* <p>
* Manages LocalMonitoredVm instances for all JVMs owned by the specified
* user.
*
* @param user the name of the user
*/
public LocalVmManager(String user) {
this.userName = user;
if (userName == null) {
tmpdir = new File(PerfDataFile.getTempDirectory());
userPattern = Pattern.compile(PerfDataFile.userDirNamePattern);
userMatcher = userPattern.matcher("");
userFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
userMatcher.reset(name);
return userMatcher.lookingAt();
}
};
} else {
tmpdir = new File(PerfDataFile.getTempDirectory(userName));
}
filePattern = Pattern.compile(PerfDataFile.fileNamePattern);
fileMatcher = filePattern.matcher("");
fileFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
fileMatcher.reset(name);
return fileMatcher.matches();
}
};
tmpFilePattern = Pattern.compile(PerfDataFile.tmpFileNamePattern);
tmpFileMatcher = tmpFilePattern.matcher("");
tmpFileFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
tmpFileMatcher.reset(name);
return tmpFileMatcher.matches();
}
};
}
/**
* Return the current set of monitorable Java Virtual Machines.
* <p>
* The set returned by this method depends on the user name passed
* to the constructor. If no user name was specified, then this
* method will return all candidate JVMs on the system. Otherwise,
* only the JVMs for the given user will be returned. This assumes
* that principal associated with this JVM has the appropriate
* permissions to access the target set of JVMs.
*
* @return Set - the Set of monitorable Java Virtual Machines
*/
public synchronized Set<Integer> activeVms() {
/*
* This method is synchronized because the Matcher object used by
* fileFilter is not safe for concurrent use, and this method is
* called by multiple threads. Before this method was synchronized,
* we'd see strange file names being matched by the matcher.
*/
Set<Integer> jvmSet = new HashSet<Integer>();
if (! tmpdir.isDirectory()) {
return jvmSet;
}
if (userName == null) {
/*
* get a list of all of the user temporary directories and
* iterate over the list to find any files within those directories.
*/
File[] dirs = tmpdir.listFiles(userFilter);
for (int i = 0 ; i < dirs.length; i ++) {
if (!dirs[i].isDirectory()) {
continue;
}
// get a list of files from the directory
File[] files = dirs[i].listFiles(fileFilter);
if (files != null) {
for (int j = 0; j < files.length; j++) {
if (files[j].isFile() && files[j].canRead()) {
jvmSet.add(new Integer(
PerfDataFile.getLocalVmId(files[j])));
}
}
}
}
} else {
/*
* Check if the user directory can be accessed. Any of these
* conditions may have asynchronously changed between subsequent
* calls to this method.
*/
// get the list of files from the specified user directory
File[] files = tmpdir.listFiles(fileFilter);
if (files != null) {
for (int j = 0; j < files.length; j++) {
if (files[j].isFile() && files[j].canRead()) {
jvmSet.add(new Integer(
PerfDataFile.getLocalVmId(files[j])));
}
}
}
}
// look for any 1.4.1 files
File[] files = tmpdir.listFiles(tmpFileFilter);
if (files != null) {
for (int j = 0; j < files.length; j++) {
if (files[j].isFile() && files[j].canRead()) {
jvmSet.add(new Integer(
PerfDataFile.getLocalVmId(files[j])));
}
}
}
return jvmSet;
}
}

View File

@@ -0,0 +1,223 @@
/*
* Copyright (c) 2004, 2008, 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.protocol.local;
import sun.jvmstat.monitor.*;
import sun.jvmstat.monitor.event.*;
import sun.jvmstat.perfdata.monitor.*;
import java.util.*;
import java.net.*;
/**
* Concrete implementation of the MonitoredHost interface for the
* <em>local</em> protocol of the HotSpot PerfData monitoring implementation.
*
* @author Brian Doherty
* @since 1.5
*/
public class MonitoredHostProvider extends MonitoredHost {
private static final int DEFAULT_POLLING_INTERVAL = 1000;
private ArrayList<HostListener> listeners;
private NotifierTask task;
private HashSet<Integer> activeVms;
private LocalVmManager vmManager;
/**
* Create a MonitoredHostProvider instance using the given HostIdentifier.
*
* @param hostId the host identifier for this MonitoredHost
*/
public MonitoredHostProvider(HostIdentifier hostId) {
this.hostId = hostId;
this.listeners = new ArrayList<HostListener>();
this.interval = DEFAULT_POLLING_INTERVAL;
this.activeVms = new HashSet<Integer>();
this.vmManager = new LocalVmManager();
}
/**
* {@inheritDoc}
*/
public MonitoredVm getMonitoredVm(VmIdentifier vmid)
throws MonitorException {
return getMonitoredVm(vmid, DEFAULT_POLLING_INTERVAL);
}
/**
* {@inheritDoc}
*/
public MonitoredVm getMonitoredVm(VmIdentifier vmid, int interval)
throws MonitorException {
try {
VmIdentifier nvmid = hostId.resolve(vmid);
return new LocalMonitoredVm(nvmid, interval);
} catch (URISyntaxException e) {
/*
* the VmIdentifier is expected to be a valid and it should
* resolve reasonably against the host identifier. A
* URISyntaxException here is most likely a programming error.
*/
throw new IllegalArgumentException("Malformed URI: "
+ vmid.toString(), e);
}
}
/**
* {@inheritDoc}
*/
public void detach(MonitoredVm vm) {
vm.detach();
}
/**
* {@inheritDoc}
*/
public void addHostListener(HostListener listener) {
synchronized(listeners) {
listeners.add(listener);
if (task == null) {
task = new NotifierTask();
LocalEventTimer timer = LocalEventTimer.getInstance();
timer.schedule(task, interval, interval);
}
}
}
/**
* {@inheritDoc}
*/
public void removeHostListener(HostListener listener) {
synchronized(listeners) {
listeners.remove(listener);
if (listeners.isEmpty() && (task != null)) {
task.cancel();
task = null;
}
}
}
/**
* {@inheritDoc}
*/
public void setInterval(int newInterval) {
synchronized(listeners) {
if (newInterval == interval) {
return;
}
int oldInterval = interval;
super.setInterval(newInterval);
if (task != null) {
task.cancel();
NotifierTask oldTask = task;
task = new NotifierTask();
LocalEventTimer timer = LocalEventTimer.getInstance();
CountedTimerTaskUtils.reschedule(timer, oldTask, task,
oldInterval, newInterval);
}
}
}
/**
* {@inheritDoc}
*/
public Set<Integer> activeVms() {
return vmManager.activeVms();
}
/**
* Fire VmEvent events.
*
* @param active a set of Integer objects containing the vmid of
* the active Vms
* @param started a set of Integer objects containing the vmid of
* new Vms started since last interval.
* @param terminated a set of Integer objects containing the vmid of
* terminated Vms since last interval.
*/
private void fireVmStatusChangedEvents(Set active, Set started,
Set terminated) {
ArrayList registered = null;
VmStatusChangeEvent ev = null;
synchronized(listeners) {
registered = (ArrayList)listeners.clone();
}
for (Iterator i = registered.iterator(); i.hasNext(); /* empty */) {
HostListener l = (HostListener)i.next();
if (ev == null) {
ev = new VmStatusChangeEvent(this, active, started, terminated);
}
l.vmStatusChanged(ev);
}
}
/**
* Class to poll the local system and generate event notifications.
*/
private class NotifierTask extends CountedTimerTask {
public void run() {
super.run();
// save the last set of active JVMs
Set lastActiveVms = activeVms;
// get the current set of active JVMs
activeVms = (HashSet<Integer>)vmManager.activeVms();
if (activeVms.isEmpty()) {
return;
}
Set<Integer> startedVms = new HashSet<Integer>();
Set<Object> terminatedVms = new HashSet<Object>();
for (Iterator i = activeVms.iterator(); i.hasNext(); /* empty */) {
Integer vmid = (Integer)i.next();
if (!lastActiveVms.contains(vmid)) {
// a new file has been detected, add to set
startedVms.add(vmid);
}
}
for (Iterator i = lastActiveVms.iterator(); i.hasNext();
/* empty */) {
Object o = i.next();
if (!activeVms.contains(o)) {
// JVM has terminated, remove it from the active list
terminatedVms.add(o);
}
}
if (!startedVms.isEmpty() || !terminatedVms.isEmpty()) {
fireVmStatusChangedEvents(activeVms, startedVms,
terminatedVms);
}
}
}
}

View File

@@ -0,0 +1,95 @@
/*
* 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.protocol.local;
import sun.misc.Perf;
import sun.jvmstat.monitor.*;
import sun.jvmstat.perfdata.monitor.*;
import java.util.*;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.lang.reflect.Constructor;
import java.security.AccessController;
/**
* The concrete PerfDataBuffer implementation for the <em>local:</em>
* protocol for the HotSpot PerfData monitoring implementation.
* <p>
* This class is responsible for acquiring access to the shared memory
* instrumentation buffer for the target HotSpot Java Virtual Machine.
*
* @author Brian Doherty
* @since 1.5
*/
// Suppreess unchecked conversion warning at line 34.
//@SuppressWarnings("unchecked")
public class PerfDataBuffer extends AbstractPerfDataBuffer {
private static final Perf perf = AccessController.doPrivileged(new Perf.GetPerfAction());
/**
* Create a PerfDataBuffer instance for accessing the specified
* instrumentation buffer.
*
* @param vmid the <em>local:</em> URI specifying the target JVM.
*
* @throws MonitorException
*/
public PerfDataBuffer(VmIdentifier vmid) throws MonitorException {
try {
// Try 1.4.2 and later first
ByteBuffer bb = perf.attach(vmid.getLocalVmId(), vmid.getMode());
createPerfDataBuffer(bb, vmid.getLocalVmId());
} catch (IllegalArgumentException e) {
// now try 1.4.1 by attempting to directly map the files.
try {
String filename = PerfDataFile.getTempDirectory()
+ PerfDataFile.dirNamePrefix
+ Integer.toString(vmid.getLocalVmId());
File f = new File(filename);
FileChannel fc = new RandomAccessFile(f, "r").getChannel();
ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0L,
(int)fc.size());
fc.close();
createPerfDataBuffer(bb, vmid.getLocalVmId());
} catch (FileNotFoundException e2) {
// re-throw the exception from the 1.4.2 attach method
throw new MonitorException(vmid.getLocalVmId() + " not found",
e);
} catch (IOException e2) {
throw new MonitorException("Could not map 1.4.1 file for "
+ vmid.getLocalVmId(), e2);
}
} catch (IOException e) {
throw new MonitorException("Could not attach to "
+ vmid.getLocalVmId(), e);
}
}
}

View File

@@ -0,0 +1,307 @@
/*
* 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.protocol.local;
import java.io.File;
import java.io.FilenameFilter;
/**
* Class to provide translations from the local Vm Identifier
* name space into the file system name space and vice-versa.
* <p>
* Provides a factory for creating a File object to the backing
* store file for instrumentation shared memory region for a JVM
* identified by its Local Java Virtual Machine Identifier, or
* <em>lvmid</em>.
*
* @author Brian Doherty
* @since 1.5
* @see java.io.File
*/
public class PerfDataFile {
private PerfDataFile() { };
/**
* The name of the of the system dependent temporary directory
*/
public static final String tmpDirName;
/**
* The file name prefix for PerfData shared memory files.
* <p>
* This prefix must be kept in sync with the prefix used by the JVM.
*/
public static final String dirNamePrefix = "hsperfdata_";
/**
* The directory name pattern for the user directories.
*/
public static final String userDirNamePattern = "hsperfdata_\\S*";
/**
* The file name pattern for PerfData shared memory files.
* <p>
* This pattern must be kept in synch with the file name pattern
* used by the 1.4.2 and later HotSpot JVM.
*/
public static final String fileNamePattern = "^[0-9]+$";
/**
* The file name pattern for 1.4.1 PerfData shared memory files.
* <p>
* This pattern must be kept in synch with the file name pattern
* used by the 1.4.1 HotSpot JVM.
*/
public static final String tmpFileNamePattern =
"^hsperfdata_[0-9]+(_[1-2]+)?$";
/**
* Get a File object for the instrumentation backing store file
* for the JVM identified by the given local Vm Identifier.
* <p>
* This method looks for the most up to date backing store file for
* the given <tt>lvmid</tt>. It will search all the user specific
* directories in the temporary directory for the host operating
* system, which may be influenced by platform specific environment
* variables.
*
* @param lvmid the local Java Virtual Machine Identifier for the target
* @return File - a File object to the backing store file for the named
* shared memory region of the target JVM.
* @see java.io.File
* @see #getTempDirectory()
*/
public static File getFile(int lvmid) {
if (lvmid == 0) {
/*
* lvmid == 0 is used to indicate the current Java Virtual Machine.
* If the SDK provided an API to get a unique Java Virtual Machine
* identifier, then a filename could be constructed with that
* identifier. In absence of such an api, return null.
*/
return null;
}
/*
* iterate over all files in all directories in tmpDirName that
* match the file name patterns.
*/
File tmpDir = new File(tmpDirName);
String[] files = tmpDir.list(new FilenameFilter() {
public boolean accept(File dir, String name) {
if (!name.startsWith(dirNamePrefix)) {
return false;
}
File candidate = new File(dir, name);
return ((candidate.isDirectory() || candidate.isFile())
&& candidate.canRead());
}
});
long newestTime = 0;
File newest = null;
for (int i = 0; i < files.length; i++) {
File f = new File(tmpDirName + files[i]);
File candidate = null;
if (f.exists() && f.isDirectory()) {
/*
* found a directory matching the name patterns. This
* is a 1.4.2 hsperfdata_<user> directory. Check for
* file named <lvmid> in that directory
*/
String name = Integer.toString(lvmid);
candidate = new File(f.getName(), name);
} else if (f.exists() && f.isFile()) {
/*
* found a file matching the name patterns. This
* is a 1.4.1 hsperfdata_<lvmid> file.
*/
candidate = f;
} else {
// unexpected - let conditional below filter this one out
candidate = f;
}
if (candidate.exists() && candidate.isFile()
&& candidate.canRead()) {
long modTime = candidate.lastModified();
if (modTime >= newestTime) {
newestTime = modTime;
newest = candidate;
}
}
}
return newest;
}
/**
* Return the File object for the backing store file for the specified Java
* Virtual Machine.
* <p>
* This method looks for the most up to date backing store file for
* the JVM identified by the given user name and lvmid. The directory
* searched is the temporary directory for the host operating system,
* which may be influenced by environment variables.
*
* @param user the user name
* @param lvmid the local Java Virtual Machine Identifier for the target
* @return File - a File object to the backing store file for the named
* shared memory region of the target JVM.
* @see java.io.File
* @see #getTempDirectory()
*/
public static File getFile(String user, int lvmid) {
if (lvmid == 0) {
/*
* lvmid == 0 is used to indicate the current Java Virtual Machine.
* If the SDK provided an API to get a unique Java Virtual Machine
* identifier, then a filename could be constructed with that
* identifier. In absence of such an api, return null.
*/
return null;
}
// first try for 1.4.2 and later JVMs
String basename = getTempDirectory(user) + Integer.toString(lvmid);
File f = new File(basename);
if (f.exists() && f.isFile() && f.canRead()) {
return f;
}
// No hit on 1.4.2 JVMs, try 1.4.1 files
long newestTime = 0;
File newest = null;
for (int i = 0; i < 2; i++) {
if (i == 0) {
basename = getTempDirectory() + Integer.toString(lvmid);
} else {
basename = getTempDirectory() + Integer.toString(lvmid)
+ Integer.toString(i);
}
f = new File(basename);
if (f.exists() && f.isFile() && f.canRead()) {
long modTime = f.lastModified();
if (modTime >= newestTime) {
newestTime = modTime;
newest = f;
}
}
}
return newest;
}
/**
* Method to extract a local Java Virtual Machine Identifier from the
* file name of the given File object.
*
* @param file A File object representing the name of a
* shared memory region for a target JVM
* @return int - the local Java Virtual Machine Identifier for the target
* associated with the file
* @throws java.lang.IllegalArgumentException Thrown if the file name
* does not conform to the expected pattern
*/
public static int getLocalVmId(File file) {
try {
// try 1.4.2 and later format first
return Integer.parseInt(file.getName());
} catch (NumberFormatException e) { }
// now try the 1.4.1 format
String name = file.getName();
if (name.startsWith(dirNamePrefix)) {
int first = name.indexOf('_');
int last = name.lastIndexOf('_');
try {
if (first == last) {
return Integer.parseInt(name.substring(first + 1));
} else {
return Integer.parseInt(name.substring(first + 1, last));
}
} catch (NumberFormatException e) { }
}
throw new IllegalArgumentException("file name does not match pattern");
}
/**
* Return the name of the temporary directory being searched for
* HotSpot PerfData backing store files.
* <p>
* This method generally returns the value of the java.io.tmpdir
* property. However, on some platforms it may return a different
* directory, as the JVM implementation may store the PerfData backing
* store files in a different directory for performance reasons.
*
* @return String - the name of the temporary directory.
*/
public static String getTempDirectory() {
return tmpDirName;
}
/**
* Return the name of the temporary directory to be searched
* for HotSpot PerfData backing store files for a given user.
* <p>
* This method generally returns the name of a subdirectory of
* the directory indicated in the java.io.tmpdir property. However,
* on some platforms it may return a different directory, as the
* JVM implementation may store the PerfData backing store files
* in a different directory for performance reasons.
*
* @return String - the name of the temporary directory.
*/
public static String getTempDirectory(String user) {
return tmpDirName + dirNamePrefix + user + File.separator;
}
static {
/*
* For this to work, the target VM and this code need to use
* the same directory. Instead of guessing which directory the
* VM is using, we will ask.
*/
String tmpdir = sun.misc.VMSupport.getVMTemporaryDirectory();
/*
* Assure that the string returned has a trailing File.separator
* character. This check was added because the Linux implementation
* changed such that the java.io.tmpdir string no longer terminates
* with a File.separator character.
*/
if (tmpdir.lastIndexOf(File.separator) != (tmpdir.length()-1)) {
tmpdir = tmpdir + File.separator;
}
tmpDirName = tmpdir;
}
}

View File

@@ -0,0 +1,341 @@
/*
* 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.protocol.rmi;
import sun.jvmstat.monitor.*;
import sun.jvmstat.monitor.event.*;
import sun.jvmstat.monitor.remote.*;
import sun.jvmstat.perfdata.monitor.*;
import java.util.*;
import java.net.*;
import java.io.*;
import java.rmi.*;
import java.util.HashMap;
/**
* Concrete implementation of the MonitoredHost interface for the
* <em>rmi</em> protocol of the HotSpot PerfData monitoring implementation.
*
* @author Brian Doherty
* @since 1.5
*/
public class MonitoredHostProvider extends MonitoredHost {
private static final String serverName = "/JStatRemoteHost";
private static final int DEFAULT_POLLING_INTERVAL = 1000;
private ArrayList<HostListener> listeners;
private NotifierTask task;
private HashSet<Integer> activeVms;
private RemoteVmManager vmManager;
private RemoteHost remoteHost;
private Timer timer;
/**
* Create a MonitoredHostProvider instance using the given HostIdentifier.
*
* @param hostId the host identifier for this MonitoredHost
* @throws MonitorException Thrown on any error encountered while
* communicating with the remote host.
*/
public MonitoredHostProvider(HostIdentifier hostId)
throws MonitorException {
this.hostId = hostId;
this.listeners = new ArrayList<HostListener>();
this.interval = DEFAULT_POLLING_INTERVAL;
this.activeVms = new HashSet<Integer>();
String rmiName;
String sn = serverName;
String path = hostId.getPath();
if ((path != null) && (path.length() > 0)) {
sn = path;
}
if (hostId.getPort() != -1) {
rmiName = "rmi://" + hostId.getHost() + ":" + hostId.getPort() + sn;
} else {
rmiName = "rmi://" + hostId.getHost() + sn;
}
try {
remoteHost = (RemoteHost)Naming.lookup(rmiName);
} catch (RemoteException e) {
/*
* rmi registry not available
*
* Access control exceptions, where the rmi server refuses a
* connection based on policy file configuration, come through
* here on the client side. Unfortunately, the RemoteException
* doesn't contain enough information to determine the true cause
* of the exception. So, we have to output a rather generic message.
*/
String message = "RMI Registry not available at "
+ hostId.getHost();
if (hostId.getPort() == -1) {
message = message + ":"
+ java.rmi.registry.Registry.REGISTRY_PORT;
} else {
message = message + ":" + hostId.getPort();
}
if (e.getMessage() != null) {
throw new MonitorException(message + "\n" + e.getMessage(), e);
} else {
throw new MonitorException(message, e);
}
} catch (NotBoundException e) {
// no server with given name
String message = e.getMessage();
if (message == null) message = rmiName;
throw new MonitorException("RMI Server " + message
+ " not available", e);
} catch (MalformedURLException e) {
// this is a programming problem
e.printStackTrace();
throw new IllegalArgumentException("Malformed URL: " + rmiName);
}
this.vmManager = new RemoteVmManager(remoteHost);
this.timer = new Timer(true);
}
/**
* {@inheritDoc}
*/
public MonitoredVm getMonitoredVm(VmIdentifier vmid)
throws MonitorException {
return getMonitoredVm(vmid, DEFAULT_POLLING_INTERVAL);
}
/**
* {@inheritDoc}
*/
public MonitoredVm getMonitoredVm(VmIdentifier vmid, int interval)
throws MonitorException {
VmIdentifier nvmid = null;
try {
nvmid = hostId.resolve(vmid);
RemoteVm rvm = remoteHost.attachVm(vmid.getLocalVmId(),
vmid.getMode());
RemoteMonitoredVm rmvm = new RemoteMonitoredVm(rvm, nvmid, timer,
interval);
rmvm.attach();
return rmvm;
} catch (RemoteException e) {
throw new MonitorException("Remote Exception attaching to "
+ nvmid.toString(), e);
} catch (URISyntaxException e) {
/*
* the VmIdentifier is expected to be a valid and should resolve
* easonably against the host identifier. A URISyntaxException
* here is most likely a programming error.
*/
throw new IllegalArgumentException("Malformed URI: "
+ vmid.toString(), e);
}
}
/**
* {@inheritDoc}
*/
public void detach(MonitoredVm vm) throws MonitorException {
RemoteMonitoredVm rmvm = (RemoteMonitoredVm)vm;
rmvm.detach();
try {
remoteHost.detachVm(rmvm.getRemoteVm());
} catch (RemoteException e) {
throw new MonitorException("Remote Exception detaching from "
+ vm.getVmIdentifier().toString(), e);
}
}
/**
* {@inheritDoc}
*/
public void addHostListener(HostListener listener) {
synchronized(listeners) {
listeners.add(listener);
if (task == null) {
task = new NotifierTask();
timer.schedule(task, 0, interval);
}
}
}
/**
* {@inheritDoc}
*/
public void removeHostListener(HostListener listener) {
/*
* XXX: if a disconnect method is added, make sure it calls
* this method to unregister this object from the watcher. otherwise,
* an unused MonitoredHostProvider instance may go uncollected.
*/
synchronized(listeners) {
listeners.remove(listener);
if (listeners.isEmpty() && (task != null)) {
task.cancel();
task = null;
}
}
}
public void setInterval(int newInterval) {
synchronized(listeners) {
if (newInterval == interval) {
return;
}
int oldInterval = interval;
super.setInterval(newInterval);
if (task != null) {
task.cancel();
NotifierTask oldTask = task;
task = new NotifierTask();
CountedTimerTaskUtils.reschedule(timer, oldTask, task,
oldInterval, newInterval);
}
}
}
/**
* {@inheritDoc}
*/
public Set<Integer> activeVms() throws MonitorException {
return vmManager.activeVms();
}
/**
* Fire VmStatusChangeEvent events to HostListener objects
*
* @param active Set of Integer objects containing the local
* Vm Identifiers of the active JVMs
* @param started Set of Integer objects containing the local
* Vm Identifiers of new JVMs started since last
* interval.
* @param terminated Set of Integer objects containing the local
* Vm Identifiers of terminated JVMs since last
* interval.
*/
private void fireVmStatusChangedEvents(Set active, Set started,
Set terminated) {
ArrayList registered = null;
VmStatusChangeEvent ev = null;
synchronized(listeners) {
registered = (ArrayList)listeners.clone();
}
for (Iterator i = registered.iterator(); i.hasNext(); /* empty */) {
HostListener l = (HostListener)i.next();
if (ev == null) {
ev = new VmStatusChangeEvent(this, active, started, terminated);
}
l.vmStatusChanged(ev);
}
}
/**
* Fire hostDisconnectEvent events.
*/
void fireDisconnectedEvents() {
ArrayList registered = null;
HostEvent ev = null;
synchronized(listeners) {
registered = (ArrayList)listeners.clone();
}
for (Iterator i = registered.iterator(); i.hasNext(); /* empty */) {
HostListener l = (HostListener)i.next();
if (ev == null) {
ev = new HostEvent(this);
}
l.disconnected(ev);
}
}
/**
* class to poll the remote machine and generate local event notifications.
*/
private class NotifierTask extends CountedTimerTask {
public void run() {
super.run();
// save the last set of active JVMs
Set lastActiveVms = activeVms;
try {
// get the current set of active JVMs
activeVms = (HashSet<Integer>)vmManager.activeVms();
} catch (MonitorException e) {
// XXX: use logging api
System.err.println("MonitoredHostProvider: polling task "
+ "caught MonitorException:");
e.printStackTrace();
// mark the HostManager as errored and notify listeners
setLastException(e);
fireDisconnectedEvents();
}
if (activeVms.isEmpty()) {
return;
}
Set<Integer> startedVms = new HashSet<Integer>();
Set<Object> terminatedVms = new HashSet<Object>();
for (Iterator i = activeVms.iterator(); i.hasNext(); /* empty */ ) {
Integer vmid = (Integer)i.next();
if (!lastActiveVms.contains(vmid)) {
// a new file has been detected, add to set
startedVms.add(vmid);
}
}
for (Iterator i = lastActiveVms.iterator(); i.hasNext();
/* empty */ ) {
Object o = i.next();
if (!activeVms.contains(o)) {
// JVM has terminated, remove it from the active list
terminatedVms.add(o);
}
}
if (!startedVms.isEmpty() || !terminatedVms.isEmpty()) {
fireVmStatusChangedEvents(activeVms, startedVms, terminatedVms);
}
}
}
}

View File

@@ -0,0 +1,92 @@
/*
* 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.protocol.rmi;
import sun.jvmstat.monitor.*;
import sun.jvmstat.monitor.remote.*;
import sun.jvmstat.perfdata.monitor.*;
import java.io.*;
import java.rmi.RemoteException;
import java.nio.ByteBuffer;
/**
* The concrete PerfDataBuffer implementation for the <em>rmi:</em>
* protocol for the HotSpot PerfData monitoring implementation.
* <p>
* This class is responsible for acquiring the instrumentation buffer
* data for a remote target HotSpot Java Virtual Machine.
*
* @author Brian Doherty
* @since 1.5
*/
public class PerfDataBuffer extends AbstractPerfDataBuffer {
private RemoteVm rvm;
/**
* Create a PerfDataBuffer instance for accessing the specified
* instrumentation buffer.
*
* @param rvm the proxy to the remote MonitredVm object
* @param lvmid the local Java Virtual Machine Identifier of the
* remote target.
*
* @throws MonitorException
*/
public PerfDataBuffer(RemoteVm rvm, int lvmid) throws MonitorException {
this.rvm = rvm;
try {
ByteBuffer buffer = ByteBuffer.allocate(rvm.getCapacity());
sample(buffer);
createPerfDataBuffer(buffer, lvmid);
} catch (RemoteException e) {
throw new MonitorException("Could not read data for remote JVM "
+ lvmid, e);
}
}
/**
* Get a copy of the remote instrumentation buffer.
*<p>
* The data in the remote instrumentation buffer is copied into
* the local byte buffer.
*
* @param buffer the buffer to receive the copy of the remote
* instrumentation buffer.
* @throws RemoteException Thrown on any communications errors with
* the remote system.
*/
public void sample(ByteBuffer buffer) throws RemoteException {
assert buffer != null;
assert rvm != null;
synchronized(buffer) {
buffer.clear();
buffer.put(rvm.getBytes());
}
}
}

View File

@@ -0,0 +1,298 @@
/*
* 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.protocol.rmi;
import sun.jvmstat.monitor.*;
import sun.jvmstat.monitor.event.*;
import sun.jvmstat.monitor.remote.*;
import sun.jvmstat.perfdata.monitor.*;
import java.lang.reflect.*;
import java.util.*;
import java.io.*;
import java.nio.ByteBuffer;
import java.rmi.*;
/**
* Concrete implementation of the AbstractMonitoredVm class for the
* <em>rmi:</em> protocol for the HotSpot PerfData monitoring implementation.
* <p>
* This class provides the ability to acquire to the instrumentation buffer
* of a live, remote target Java Virtual Machine through an RMI server.
*
* @author Brian Doherty
* @since 1.5
*/
public class RemoteMonitoredVm extends AbstractMonitoredVm {
private ArrayList<VmListener> listeners;
private NotifierTask notifierTask;
private SamplerTask samplerTask;
private Timer timer;
private RemoteVm rvm;
private ByteBuffer updateBuffer;
/**
* Create a RemoteMonitoredVm instance.
*
* @param rvm the proxy to the remote MonitoredVm instance.
* @param vmid the vm identifier specifying the remot target JVM
* @param timer the timer used to run polling tasks
* @param interval the sampling interval
*/
public RemoteMonitoredVm(RemoteVm rvm, VmIdentifier vmid,
Timer timer, int interval)
throws MonitorException {
super(vmid, interval);
this.rvm = rvm;
pdb = new PerfDataBuffer(rvm, vmid.getLocalVmId());
this.listeners = new ArrayList<VmListener>();
this.timer = timer;
}
/**
* Method to attach to the remote MonitoredVm.
*/
public void attach() throws MonitorException {
updateBuffer = pdb.getByteBuffer().duplicate();
// if continuous sampling is requested, register with the sampler thread
if (interval > 0) {
samplerTask = new SamplerTask();
timer.schedule(samplerTask, 0, interval);
}
}
/**
* {@inheritDoc}
*/
public void detach() {
try {
if (interval > 0) {
if (samplerTask != null) {
samplerTask.cancel();
samplerTask = null;
}
if (notifierTask != null) {
notifierTask.cancel();
notifierTask = null;
}
sample();
}
} catch (RemoteException e) {
// XXX: - use logging api? throw an exception instead?
System.err.println("Could not read data for remote JVM " + vmid);
e.printStackTrace();
} finally {
super.detach();
}
}
/**
* Get a copy of the remote instrumentation buffer.
*<p>
* The data in the remote instrumentation buffer is copied into
* a local byte buffer.
*
* @throws RemoteException Thrown on any communications errors with
* the remote system.
*/
public void sample() throws RemoteException {
assert updateBuffer != null;
((PerfDataBuffer)pdb).sample(updateBuffer);
}
/**
* Get the proxy to the remote MonitoredVm.
*
* @return RemoteVm - the proxy to the remote MonitoredVm.
*/
public RemoteVm getRemoteVm() {
return rvm;
}
/**
* {@inheritDoc}
*/
public void addVmListener(VmListener l) {
synchronized(listeners) {
listeners.add(l);
if (notifierTask == null) {
notifierTask = new NotifierTask();
timer.schedule(notifierTask, 0, interval);
}
}
}
/**
* {@inheritDoc}
*/
public void removeVmListener(VmListener l) {
synchronized(listeners) {
listeners.remove(l);
if (listeners.isEmpty() && (notifierTask != null)) {
notifierTask.cancel();
notifierTask = null;
}
}
}
/**
* {@inheritDoc}
*/
public void setInterval(int newInterval) {
synchronized(listeners) {
if (newInterval == interval) {
return;
}
int oldInterval = interval;
super.setInterval(newInterval);
if (samplerTask != null) {
samplerTask.cancel();
SamplerTask oldSamplerTask = samplerTask;
samplerTask = new SamplerTask();
CountedTimerTaskUtils.reschedule(timer, oldSamplerTask,
samplerTask, oldInterval,
newInterval);
}
if (notifierTask != null) {
notifierTask.cancel();
NotifierTask oldNotifierTask = notifierTask;
notifierTask = new NotifierTask();
CountedTimerTaskUtils.reschedule(timer, oldNotifierTask,
notifierTask, oldInterval,
newInterval);
}
}
}
/**
* Fire MonitoredVmStructureChanged events.
*
* @param inserted List of Monitor objects inserted.
* @param removed List of Monitor objects removed.
*/
void fireMonitorStatusChangedEvents(List inserted, List removed) {
ArrayList registered = null;
MonitorStatusChangeEvent ev = null;
synchronized(listeners) {
registered = (ArrayList)listeners.clone();
}
for (Iterator i = registered.iterator(); i.hasNext(); /* empty */) {
VmListener l = (VmListener)i.next();
if (ev == null) {
ev = new MonitorStatusChangeEvent(this, inserted, removed);
}
l.monitorStatusChanged(ev);
}
}
/**
* Fire MonitoredVmStructureChanged events.
*/
void fireMonitorsUpdatedEvents() {
ArrayList registered = null;
VmEvent ev = null;
synchronized(listeners) {
registered = (ArrayList)listeners.clone();
}
for (Iterator i = registered.iterator(); i.hasNext(); /* empty */) {
VmListener l = (VmListener)i.next();
if (ev == null) {
ev = new VmEvent(this);
}
l.monitorsUpdated(ev);
}
}
/*
* Timer Tasks. There are two separate timer tasks here. The SamplerTask
* is active whenever we are attached to the remote JVM with a periodic
* sampling interval > 0. The NotifierTask is only active if a VmListener
* has registered with this RemoteMonitoredVm instance. Also, in the future
* we may want to run these tasks at different intervals. Currently,
* they run at the same interval and some significant work may
* need to be done to complete the separation of these two intervals.
*/
/**
* Class to periodically check the state of the defined monitors
* for the remote MonitoredVm instance and to notify listeners of
* any detected changes.
*/
private class NotifierTask extends CountedTimerTask {
public void run() {
super.run();
try {
MonitorStatus status = getMonitorStatus();
List inserted = status.getInserted();
List removed = status.getRemoved();
if (!inserted.isEmpty() || !removed.isEmpty()) {
fireMonitorStatusChangedEvents(inserted, removed);
}
} catch (MonitorException e) {
// XXX: use logging api? fire disconnect events? mark errored?
// fireDisconnectedEvents();
System.err.println("Exception updating monitors for "
+ getVmIdentifier());
e.printStackTrace();
// XXX: should we cancle the notifierTask here?
// this.cancel();
}
}
}
/**
* Class to periodically sample the remote instrumentation byte buffer
* and refresh the local copy. Registered listeners are notified of
* the completion of a sampling event.
*/
private class SamplerTask extends CountedTimerTask {
public void run() {
super.run();
try {
sample();
fireMonitorsUpdatedEvents();
} catch (RemoteException e) {
// XXX: use logging api, mark vm as errored.
System.err.println("Exception taking sample for "
+ getVmIdentifier());
e.printStackTrace();
this.cancel();
}
}
}
}

View File

@@ -0,0 +1,114 @@
/*
* 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.protocol.rmi;
import java.util.*;
import java.util.regex.*;
import java.io.*;
import java.rmi.RemoteException;
import sun.jvmstat.monitor.*;
import sun.jvmstat.monitor.event.*;
import sun.jvmstat.monitor.remote.*;
/**
* Class for managing the RemoteMonitoredVm instances on a remote system.
* <p>
* This class is responsible for the mechanism that detects the active
* HotSpot Java Virtual Machines on the remote host and possibly for a
* specific user. The ability to detect all possible HotSpot Java Virtual
* Machines on the remote host may be limited by the permissions of the
* principal running the RMI server application on the remote host.
*
* @author Brian Doherty
* @since 1.5
*/
public class RemoteVmManager {
private RemoteHost remoteHost;
private String user;
/**
* Creates a RemoteVmManager instance for the remote system.
* <p>
* Manages RemoteMonitordVm instances for which the principal
* running the remote server has appropriate permissions.
*
* @param remoteHost the remote proxy object to the RMI server on
* the remote system.
*/
public RemoteVmManager(RemoteHost remoteHost) {
this(remoteHost, null);
}
/**
* Creates a RemoteVmManager instance for the given user.
* <p>
* Manages RemoteMonitoredVm instances for all remote Java Virtual
* machines owned by the specified user on the remote system. The
* RMI server on the remote system must have the appropriate permissions
* to access the named users Java Virtual Machines.
*
* @param remoteHost the remote proxy object to the RMI server on
* the remote system.
* @param user the name of the user
*/
public RemoteVmManager(RemoteHost remoteHost, String user) {
this.user = user;
this.remoteHost = remoteHost;
}
/**
* Return the current set of monitorable Java Virtual Machines.
* <p>
* The set returned by this method depends on the user name passed
* to the constructor. If no user name was specified, then this
* method will return all candidate JVMs on the system. Otherwise,
* only the JVMs for the given user will be returned. This assumes
* that the RMI server process has the appropriate permissions to
* access the target set of JVMs.
*
* @return Set - the Set of monitorable Java Virtual Machines
*/
public Set<Integer> activeVms() throws MonitorException {
int[] active = null;
try {
active = remoteHost.activeVms();
} catch (RemoteException e) {
throw new MonitorException("Error communicating with remote host: "
+ e.getMessage(), e);
}
Set<Integer> activeSet = new HashSet<Integer>(active.length);
for (int i = 0; i < active.length; i++) {
activeSet.add(new Integer(active[i]));
}
return activeSet;
}
}

View File

@@ -0,0 +1,100 @@
/*
* 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.v1_0;
/**
* A typesafe enumeration for describing Java basic types.
*
* <p> The enumeration values for this typesafe enumeration must be
* kept in synchronization with the BasicType enum in the
* globalsDefinitions.hpp file in the HotSpot source base.</p>
*
* @author Brian Doherty
* @since 1.5
*/
public class BasicType {
private final String name;
private final int value;
public static final BasicType BOOLEAN = new BasicType("boolean", 4);
public static final BasicType CHAR = new BasicType("char", 5);
public static final BasicType FLOAT = new BasicType("float", 6);
public static final BasicType DOUBLE = new BasicType("double", 7);
public static final BasicType BYTE = new BasicType("byte", 8);
public static final BasicType SHORT = new BasicType("short", 9);
public static final BasicType INT = new BasicType("int", 10);
public static final BasicType LONG = new BasicType("long", 11);
public static final BasicType OBJECT = new BasicType("object", 12);
public static final BasicType ARRAY = new BasicType("array", 13);
public static final BasicType VOID = new BasicType("void", 14);
public static final BasicType ADDRESS = new BasicType("address", 15);
public static final BasicType ILLEGAL = new BasicType("illegal", 99);
private static BasicType basicTypes[] = {
BOOLEAN, CHAR, FLOAT, DOUBLE, BYTE, SHORT, INT, LONG, OBJECT,
ARRAY, VOID, ADDRESS, ILLEGAL
};
/**
* Convert enumeration value to a String.
*
* @return String - the string representation for the enumeration.
*/
public String toString() {
return name;
}
/**
* Convert enumeration to an integer value.
*
* @return int - the integer representation for the enumeration.
*/
public int intValue() {
return value;
}
/**
* Map an integer value to its corresponding BasicType object.
*
* @param i an integer representation of a BasicType
* @return BasicType - The BasicType enumeration object matching
* the value of <code>i</code>
*/
public static BasicType toBasicType(int i) {
for (int j = 0; j < basicTypes.length; j++) {
if (basicTypes[j].intValue() == j) {
return (basicTypes[j]);
}
}
return ILLEGAL;
}
private BasicType(String name, int value) {
this.name = name;
this.value = value;
}
}

View File

@@ -0,0 +1,650 @@
/*
* 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.v1_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 1.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.
*
* @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);
/*
* the following constants must be kept in sync with struct
* PerfDataEntry in perfMemory.hpp
*/
private final static int PERFDATA_ENTRYLENGTH_OFFSET=0;
private final static int PERFDATA_ENTRYLENGTH_SIZE=4; // sizeof(int)
private final static int PERFDATA_NAMELENGTH_OFFSET=4;
private final static int PERFDATA_NAMELENGTH_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_DATAATTR_OFFSET=15;
private final static int PERFDATA_DATAATTR_SIZE=1; // sizeof(byte)
private final static int PERFDATA_NAME_OFFSET=16;
PerfDataBufferPrologue prologue;
int nextEntry;
int pollForEntry;
int perfDataItem;
long lastModificationTime;
int lastUsed;
IntegerMonitor overflow;
ArrayList<Monitor> insertedMonitors;
/**
* Construct a PerfDataBufferImpl 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);
// position buffer to start of the data section
buffer.position(prologue.getSize());
nextEntry = buffer.position();
perfDataItem = 0;
int used = prologue.getUsed();
long modificationTime = prologue.getModificationTimeStamp();
Monitor m = getNextMonitorEntry();
while (m != null) {
map.put(m.getName(), m);
m = getNextMonitorEntry();
}
/*
* set the last modification data. These are set to the values
* recorded before parsing the data structure. This allows the
* the data structure to be modified while the Map is being built.
* The Map may contain more entries than indicated based on the
* time stamp, but this is handled by ignoring duplicate entries
* when the Map is updated in getNewMonitors().
*/
lastUsed = used;
lastModificationTime = modificationTime;
// synchronize with the target jvm
synchWithTarget(map);
// work around 1.4.2 counter inititization bugs
kludge(map);
insertedMonitors = new ArrayList<Monitor>(map.values());
}
/**
* {@inheritDoc}
*/
protected void getNewMonitors(Map<String, Monitor> map) throws MonitorException {
assert Thread.holdsLock(this);
int used = prologue.getUsed();
long modificationTime = prologue.getModificationTimeStamp();
if ((used > lastUsed) || (lastModificationTime > modificationTime)) {
lastUsed = used;
lastModificationTime = modificationTime;
Monitor monitor = getNextMonitorEntry();
while (monitor != null) {
String name = monitor.getName();
// guard against duplicate entries
if (!map.containsKey(name)) {
map.put(name, monitor);
/*
* insertedMonitors is null when called from pollFor()
* via buildMonitorMap(). Since we update insertedMonitors
* at the end of buildMonitorMap(), it's ok to skip the
* add here.
*/
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 or 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 to provide a gross level of synchronization with the
* target monitored jvm.
*
* gross synchronization works by polling for the hotspot.rt.hrt.ticks
* counter, which is the last counter created by the StatSampler
* initialization code. The counter is updated when the watcher thread
* starts scheduling tasks, which is the last thing done in vm
* initialization.
*/
protected void synchWithTarget(Map<String, Monitor> map) 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;
String name = "hotspot.rt.hrt.ticks";
LongMonitor ticks = (LongMonitor)pollFor(map, name, timeLimit);
/*
* loop waiting for the ticks counter to be non zero. This is
* an indication that the jvm is initialized.
*/
log("synchWithTarget: " + lvmid + " ");
while (ticks.longValue() == 0) {
log(".");
try { Thread.sleep(20); } catch (InterruptedException e) { }
if (System.currentTimeMillis() > timeLimit) {
lognl("failed: " + lvmid);
throw new MonitorException("Could Not Synchronize with target");
}
}
lognl("success: " + lvmid);
}
/**
* Method to poll the instrumentation memory for a counter with
* the given name. The polling period is bounded by the timeLimit
* argument.
*/
protected Monitor pollFor(Map<String, Monitor> map, String name, long timeLimit)
throws MonitorException {
Monitor monitor = null;
log("polling for: " + lvmid + "," + name + " ");
pollForEntry = nextEntry;
while ((monitor = map.get(name)) == null) {
log(".");
try { Thread.sleep(20); } catch (InterruptedException e) { }
long t = System.currentTimeMillis();
if ((t > timeLimit) || (overflow.intValue() > 0)) {
lognl("failed: " + lvmid + "," + name);
dumpAll(map, lvmid);
throw new MonitorException("Could not find expected counter");
}
getNewMonitors(map);
}
lognl("success: " + lvmid + "," + name);
return monitor;
}
/**
* method to make adjustments for known counter problems. This
* method depends on the availability of certain counters, which
* is generally guaranteed by the synchWithTarget() method.
*/
protected void kludge(Map<String, Monitor> map) {
if (Boolean.getBoolean("sun.jvmstat.perfdata.disableKludge")) {
// bypass all kludges
return;
}
String name = "java.vm.version";
StringMonitor jvm_version = (StringMonitor)map.get(name);
if (jvm_version == null) {
jvm_version = (StringMonitor)findByAlias(name);
}
name = "java.vm.name";
StringMonitor jvm_name = (StringMonitor)map.get(name);
if (jvm_name == null) {
jvm_name = (StringMonitor)findByAlias(name);
}
name = "hotspot.vm.args";
StringMonitor args = (StringMonitor)map.get(name);
if (args == null) {
args = (StringMonitor)findByAlias(name);
}
assert ((jvm_name != null) && (jvm_version != null) && (args != null));
if (jvm_name.stringValue().indexOf("HotSpot") >= 0) {
if (jvm_version.stringValue().startsWith("1.4.2")) {
kludgeMantis(map, args);
}
}
}
/**
* method to repair the 1.4.2 parallel scavenge counters that are
* incorrectly initialized by the JVM when UseAdaptiveSizePolicy
* is set. This bug couldn't be fixed for 1.4.2 FCS due to putback
* restrictions.
*/
private void kludgeMantis(Map<String, Monitor> map, StringMonitor args) {
/*
* the HotSpot 1.4.2 JVM with the +UseParallelGC option along
* with its default +UseAdaptiveSizePolicy option has a bug with
* the initialization of the sizes of the eden and survivor spaces.
* See bugid 4890736.
*
* note - use explicit 1.4.2 counter names here - don't update
* to latest counter names or attempt to find aliases.
*/
String cname = "hotspot.gc.collector.0.name";
StringMonitor collector = (StringMonitor)map.get(cname);
if (collector.stringValue().compareTo("PSScavenge") == 0) {
boolean adaptiveSizePolicy = true;
/*
* HotSpot processes the -XX:Flags/.hotspotrc arguments prior to
* processing the command line arguments. This allows the command
* line arguments to override any defaults set in .hotspotrc
*/
cname = "hotspot.vm.flags";
StringMonitor flags = (StringMonitor)map.get(cname);
String allArgs = flags.stringValue() + " " + args.stringValue();
/*
* ignore the -XX: prefix as it only applies to the arguments
* passed from the command line (i.e. the invocation api).
* arguments passed through .hotspotrc omit the -XX: prefix.
*/
int ahi = allArgs.lastIndexOf("+AggressiveHeap");
int aspi = allArgs.lastIndexOf("-UseAdaptiveSizePolicy");
if (ahi != -1) {
/*
* +AggressiveHeap was set, check if -UseAdaptiveSizePolicy
* is set after +AggressiveHeap.
*/
//
if ((aspi != -1) && (aspi > ahi)) {
adaptiveSizePolicy = false;
}
} else {
/*
* +AggressiveHeap not set, must be +UseParallelGC. The
* relative position of -UseAdaptiveSizePolicy is not
* important in this case, as it will override the
* UseParallelGC default (+UseAdaptiveSizePolicy) if it
* appears anywhere in the JVM arguments.
*/
if (aspi != -1) {
adaptiveSizePolicy = false;
}
}
if (adaptiveSizePolicy) {
// adjust the buggy AdaptiveSizePolicy size counters.
// first remove the real counters.
String eden_size = "hotspot.gc.generation.0.space.0.size";
String s0_size = "hotspot.gc.generation.0.space.1.size";
String s1_size = "hotspot.gc.generation.0.space.2.size";
map.remove(eden_size);
map.remove(s0_size);
map.remove(s1_size);
// get the maximum new generation size
String new_max_name = "hotspot.gc.generation.0.capacity.max";
LongMonitor new_max = (LongMonitor)map.get(new_max_name);
/*
* replace the real counters with pseudo counters that are
* initialized to to the correct values. The maximum size of
* the eden and survivor spaces are supposed to be:
* max_eden_size = new_size - (2*alignment).
* max_survivor_size = new_size - (2*alignment).
* since we don't know the alignment value used, and because
* of other parallel scavenge bugs that result in oversized
* spaces, we just set the maximum size of each space to the
* full new gen size.
*/
Monitor monitor = null;
LongBuffer lb = LongBuffer.allocate(1);
lb.put(new_max.longValue());
monitor = new PerfLongMonitor(eden_size, Units.BYTES,
Variability.CONSTANT, false, lb);
map.put(eden_size, monitor);
monitor = new PerfLongMonitor(s0_size, Units.BYTES,
Variability.CONSTANT, false, lb);
map.put(s0_size, monitor);
monitor = new PerfLongMonitor(s1_size, Units.BYTES,
Variability.CONSTANT, false, lb);
map.put(s1_size, monitor);
}
}
}
/**
* 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(
"Entry index not properly aligned: " + nextEntry);
}
// protect against a corrupted shared memory region.
if ((nextEntry < 0) || (nextEntry > buffer.limit())) {
throw new MonitorStructureException(
"Entry index out of bounds: nextEntry = " + nextEntry
+ ", limit = " + buffer.limit());
}
// check for the end of the buffer
if (nextEntry == buffer.limit()) {
lognl("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);
}
// check if last entry occurs before the eof.
if ((entryStart + entryLength) > buffer.limit()) {
throw new MonitorStructureException(
"Entry extends beyond end of buffer: "
+ " entryStart = " + entryStart
+ " entryLength = " + entryLength
+ " buffer limit = " + buffer.limit());
}
if (entryLength == 0) {
// end of data
return null;
}
int nameLength = buffer.getInt();
int vectorLength = buffer.getInt();
byte dataType = buffer.get();
byte flags = buffer.get();
Units u = Units.toUnits(buffer.get());
Variability v = Variability.toVariability(buffer.get());
boolean supported = (flags & 0x01) != 0;
// defend against corrupt entries
if ((nameLength <= 0) || (nameLength > entryLength)) {
throw new MonitorStructureException(
"Invalid Monitor name length: " + nameLength);
}
if ((vectorLength < 0) || (vectorLength > entryLength)) {
throw new MonitorStructureException(
"Invalid Monitor vector length: " + vectorLength);
}
// read in the perfData item name, casting bytes to chars. skip the
// null terminator
//
byte[] nameBytes = new byte[nameLength-1];
for (int i = 0; i < nameLength-1; i++) {
nameBytes[i] = buffer.get();
}
// convert name into a String
String name = new String(nameBytes, 0, nameLength-1);
if (v == Variability.INVALID) {
throw new MonitorDataException("Invalid variability attribute:"
+ " entry index = " + perfDataItem
+ " name = " + name);
}
if (u == Units.INVALID) {
throw new MonitorDataException("Invalid units attribute: "
+ " entry index = " + perfDataItem
+ " name = " + name);
}
int offset;
if (vectorLength == 0) {
// scalar Types
if (dataType == BasicType.LONG.intValue()) {
offset = entryStart + entryLength - 8; /* 8 = sizeof(long) */
buffer.position(offset);
LongBuffer lb = buffer.asLongBuffer();
lb.limit(1);
monitor = new PerfLongMonitor(name, u, v, supported, lb);
perfDataItem++;
} else {
// bad data types.
throw new MonitorTypeException("Invalid Monitor type:"
+ " entry index = " + perfDataItem
+ " name = " + name
+ " type = " + dataType);
}
} else {
// vector types
if (dataType == BasicType.BYTE.intValue()) {
if (u != Units.STRING) {
// only byte arrays of type STRING are currently supported
throw new MonitorTypeException("Invalid Monitor type:"
+ " entry index = " + perfDataItem
+ " name = " + name
+ " type = " + dataType);
}
offset = entryStart + PERFDATA_NAME_OFFSET + nameLength;
buffer.position(offset);
ByteBuffer bb = buffer.slice();
bb.limit(vectorLength);
bb.position(0);
if (v == Variability.CONSTANT) {
monitor = new PerfStringConstantMonitor(name, supported,
bb);
} else if (v == Variability.VARIABLE) {
monitor = new PerfStringVariableMonitor(name, supported,
bb, vectorLength-1);
} else {
// Monotonically increasing byte arrays are not supported
throw new MonitorDataException(
"Invalid variability attribute:"
+ " entry index = " + perfDataItem
+ " name = " + name
+ " variability = " + v);
}
perfDataItem++;
} else {
// bad data types.
throw new MonitorTypeException(
"Invalid Monitor type:" + " entry index = "
+ perfDataItem + " name = " + name
+ " type = " + dataType);
}
}
// 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 map, int lvmid) {
if (DEBUG) {
Set keys = map.keySet();
System.err.println("Dump for " + lvmid);
int j = 0;
for (Iterator i = keys.iterator(); i.hasNext(); j++) {
Monitor monitor = (Monitor)map.get(i.next());
System.err.println(j + "\t" + monitor.getName()
+ "=" + monitor.getValue());
}
System.err.println("nextEntry = " + nextEntry
+ " pollForEntry = " + pollForEntry);
System.err.println("Buffer info:");
System.err.println("buffer = " + buffer);
}
}
private void lognl(String s) {
if (DEBUG) {
System.err.println(s);
}
}
private void log(String s) {
if (DEBUG) {
System.err.print(s);
}
}
}

View File

@@ -0,0 +1,209 @@
/*
* 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.v1_0;
import sun.jvmstat.monitor.*;
import sun.jvmstat.perfdata.monitor.*;
import java.nio.*;
/**
* Class representing the 1.0 version of the HotSpot PerfData instrumentation
* buffer header.
* <p>
* The PerfDataBufferPrologue2_0 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
* } PerfDataPrologue
* </pre>
*
* @author Brian Doherty
* @since 1.5
*/
public class PerfDataBufferPrologue extends AbstractPerfDataBufferPrologue {
private static final int SUPPORTED_MAJOR_VERSION = 1;
private static final int SUPPORTED_MINOR_VERSION = 0;
/*
* the following constants must match the field offsets and sizes
* in the PerfDataPrologue structure in perfMemory.hpp
*/
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_SIZE=24; // sizeof(struct PerfDataProlog)
// counter names for prologue psuedo counters
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";
/**
* 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() == 1) && (getMinorVersion() == 0));
}
/**
* {@inheritDoc}
*/
public boolean supportsAccessible() {
return false;
}
/**
* {@inheritDoc}
*/
public boolean isAccessible() {
return true;
}
/**
* 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();
}
/**
* {@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()
*/
public 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()
*/
public 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()
*/
public IntBuffer overflowBuffer() {
byteBuffer.position(PERFDATA_PROLOG_OVERFLOW_OFFSET);
IntBuffer ib = byteBuffer.asIntBuffer();
ib.limit(1);
return ib;
}
/**
* Return an 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()
*/
public LongBuffer modificationTimeStampBuffer() {
byteBuffer.position(PERFDATA_PROLOG_MODTIMESTAMP_OFFSET);
LongBuffer lb = byteBuffer.asLongBuffer();
lb.limit(1);
return lb;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View 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;
}
}