feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
@@ -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) { }
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user