summaryrefslogtreecommitdiff
path: root/java/jdk16/files/patch-j2se-attach-BSDVirtualMachine.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/jdk16/files/patch-j2se-attach-BSDVirtualMachine.java')
-rw-r--r--java/jdk16/files/patch-j2se-attach-BSDVirtualMachine.java297
1 files changed, 297 insertions, 0 deletions
diff --git a/java/jdk16/files/patch-j2se-attach-BSDVirtualMachine.java b/java/jdk16/files/patch-j2se-attach-BSDVirtualMachine.java
new file mode 100644
index 000000000000..0205f5fa8f46
--- /dev/null
+++ b/java/jdk16/files/patch-j2se-attach-BSDVirtualMachine.java
@@ -0,0 +1,297 @@
+$FreeBSD$
+
+--- ../../j2se/src/solaris/classes/sun/tools/attach/BSDVirtualMachine.java 2 Feb 2009 00:28:15 -0000
++++ ../../j2se/src/solaris/classes/sun/tools/attach/BSDVirtualMachine.java 2 Feb 2009 00:28:15 -0000
+@@ -0,0 +1,292 @@
++/*
++ * @(#)BSDVirtualMachine.java 1.8 06/03/05
++ *
++ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
++ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
++ */
++package sun.tools.attach;
++
++import com.sun.tools.attach.VirtualMachine;
++import com.sun.tools.attach.AgentLoadException;
++import com.sun.tools.attach.AttachNotSupportedException;
++import com.sun.tools.attach.spi.AttachProvider;
++import java.io.InputStream;
++import java.io.IOException;
++import java.io.File;
++import java.util.Properties;
++
++/*
++ * BSD implementation of HotSpotVirtualMachine
++ */
++public class BSDVirtualMachine extends HotSpotVirtualMachine {
++
++ /**
++ * Hard-coded "/tmp" to match the hotspot bsd implementation
++ * hotspot/src/os/bsd/vm/os_bsd.cpp:
++ * const char* os::get_temp_directory() { return "/tmp/"; }
++ */
++ private static String getTmpDir() {
++ return "/tmp/";
++ }
++
++
++ String path;
++
++ /**
++ * Attaches to the target VM
++ */
++ BSDVirtualMachine(AttachProvider provider, String vmid)
++ throws AttachNotSupportedException, IOException
++ {
++ super(provider, vmid);
++
++ // This provider only understands pids
++ int pid;
++ try {
++ pid = Integer.parseInt(vmid);
++ } catch (NumberFormatException x) {
++ throw new AttachNotSupportedException("Invalid process identifier");
++ }
++
++ // Find the socket file. If not found then we attempt to start the
++ // attach mechanism in the target VM by sending it a QUIT signal.
++ // Then we attempt to find the socket file again.
++ path = findSocketFile(pid);
++ if (path == null) {
++
++ String fn = ".attach_pid" + pid;
++ path = getTmpDir() + fn;
++ File attachFile = new File(path);
++ createAttachFile(path);
++ try {
++ sendQuitTo(pid);
++
++ // give the target VM time to start the attach mechanism
++ int i = 0;
++ long delay = 200;
++ int retries = (int)(attachTimeout() / delay);
++ do {
++ try {
++ Thread.sleep(delay);
++ } catch (InterruptedException x) { }
++ path = findSocketFile(pid);
++ i++;
++ } while (i <= retries && path == null);
++ if (path == null) {
++ throw new AttachNotSupportedException(
++ "Unable to open socket file: target process not responding " +
++ "or HotSpot VM not loaded");
++ }
++ } finally {
++ attachFile.delete();
++ }
++ }
++
++ // Check that the file owner/permission to avoid attaching to
++ // bogus process
++ checkPermissions(path);
++
++ // Check that we can connect to the process
++ // - this ensures we throw the permission denied error now rather than
++ // later when we attempt to enqueue a command.
++ int s = socket();
++ try {
++ connect(s, path);
++ } finally {
++ close(s);
++ }
++ }
++
++ /**
++ * Detach from the target VM
++ */
++ public void detach() throws IOException {
++ synchronized (this) {
++ if (this.path != null) {
++ this.path = null;
++ }
++ }
++ }
++
++ // protocol version
++ private final static String PROTOCOL_VERSION = "1";
++
++ // known errors
++ private final static int ATTACH_ERROR_BADVERSION = 101;
++
++ /**
++ * Execute the given command in the target VM.
++ */
++ InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException {
++ assert args.length <= 3; // includes null
++
++ // did we detach?
++ String p;
++ synchronized (this) {
++ if (this.path == null) {
++ throw new IOException("Detached from target VM");
++ }
++ p = this.path;
++ }
++
++ // create UNIX socket
++ int s = socket();
++
++ // connect to target VM
++ try {
++ connect(s, p);
++ } catch (IOException x) {
++ close(s);
++ throw x;
++ }
++
++ IOException ioe = null;
++
++ // connected - write request
++ // <ver> <cmd> <args...>
++ try {
++ writeString(s, PROTOCOL_VERSION);
++ writeString(s, cmd);
++
++ for (int i=0; i<3; i++) {
++ if (i < args.length && args[i] != null) {
++ writeString(s, (String)args[i]);
++ } else {
++ writeString(s, "");
++ }
++ }
++ } catch (IOException x) {
++ ioe = x;
++ }
++
++
++ // Create an input stream to read reply
++ SocketInputStream sis = new SocketInputStream(s);
++
++ // Read the command completion status
++ int completionStatus;
++ try {
++ completionStatus = readInt(sis);
++ } catch (IOException x) {
++ sis.close();
++ if (ioe != null) {
++ throw ioe;
++ } else {
++ throw x;
++ }
++ }
++
++ if (completionStatus != 0) {
++ sis.close();
++
++ // In the event of a protocol mismatch then the target VM
++ // returns a known error so that we can throw a reasonable
++ // error.
++ if (completionStatus == ATTACH_ERROR_BADVERSION) {
++ throw new IOException("Protocol mismatch with target VM");
++ }
++
++ // Special-case the "load" command so that the right exception is
++ // thrown.
++ if (cmd.equals("load")) {
++ throw new AgentLoadException("Failed to load agent library");
++ } else {
++ throw new IOException("Command failed in target VM");
++ }
++ }
++
++ // Return the input stream so that the command output can be read
++ return sis;
++ }
++
++ /*
++ * InputStream for the socket connection to get target VM
++ */
++ private class SocketInputStream extends InputStream {
++ int s;
++
++ public SocketInputStream(int s) {
++ this.s = s;
++ }
++
++ public synchronized int read() throws IOException {
++ byte b[] = new byte[1];
++ int n = this.read(b, 0, 1);
++ if (n == 1) {
++ return b[0] & 0xff;
++ } else {
++ return -1;
++ }
++ }
++
++ public synchronized int read(byte[] bs, int off, int len) throws IOException {
++ if ((off < 0) || (off > bs.length) || (len < 0) ||
++ ((off + len) > bs.length) || ((off + len) < 0)) {
++ throw new IndexOutOfBoundsException();
++ } else if (len == 0)
++ return 0;
++
++ return BSDVirtualMachine.read(s, bs, off, len);
++ }
++
++ public void close() throws IOException {
++ BSDVirtualMachine.close(s);
++ }
++ }
++
++
++ // Return the socket file for the given process.
++ // Checks working directory of process for .java_pid<pid>. If not
++ // found it looks in /tmp.
++ private String findSocketFile(int pid) {
++ // First check for a .java_pid<pid> file in the working directory
++ // of the target process
++ String fn = ".java_pid" + pid;
++ String path = getTmpDir() + fn;
++ File f = new File(path);
++
++ if (!f.exists()) {
++ return null; // not found
++ }
++ return path;
++ }
++
++ /*
++ * Write/sends the given to the target VM. String is transmitted in
++ * UTF-8 encoding.
++ */
++ private void writeString(int fd, String s) throws IOException {
++ if (s.length() > 0) {
++ byte b[];
++ try {
++ b = s.getBytes("UTF-8");
++ } catch (java.io.UnsupportedEncodingException x) {
++ throw new InternalError();
++ }
++ BSDVirtualMachine.write(fd, b, 0, b.length);
++ }
++ byte b[] = new byte[1];
++ b[0] = 0;
++ write(fd, b, 0, 1);
++ }
++
++
++ static native void sendQuitTo(int pid) throws IOException;
++
++ static native void checkPermissions(String path) throws IOException;
++
++ static native int socket() throws IOException;
++
++ static native void connect(int fd, String path) throws IOException;
++
++ static native void close(int fd) throws IOException;
++
++ static native int read(int fd, byte buf[], int off, int bufLen) throws IOException;
++
++ static native void write(int fd, byte buf[], int off, int bufLen) throws IOException;
++ static native void createAttachFile(String path);
++
++ static {
++ System.loadLibrary("attach");
++ }
++}