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