8299518: HotSpotVirtualMachine shared code across different platforms

Reviewed-by: cjplummer, dholmes
This commit is contained in:
Yi Yang 2023-03-06 02:02:29 +00:00
parent 148900c2dc
commit 10d6a8e66a
5 changed files with 155 additions and 301 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2019 SAP SE. All rights reserved. * Copyright (c) 2015, 2019 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -25,7 +25,6 @@
*/ */
package sun.tools.attach; package sun.tools.attach;
import com.sun.tools.attach.AttachOperationFailedException;
import com.sun.tools.attach.AgentLoadException; import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException; import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.spi.AttachProvider; import com.sun.tools.attach.spi.AttachProvider;
@ -57,13 +56,8 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
super(provider, vmid); super(provider, vmid);
// This provider only understands pids // This provider only understands pids
int pid; int pid = Integer.parseInt(vmid);
try { if (pid < 1) {
pid = Integer.parseInt(vmid);
if (pid < 1) {
throw new NumberFormatException();
}
} catch (NumberFormatException x) {
throw new AttachNotSupportedException("Invalid process identifier: " + vmid); throw new AttachNotSupportedException("Invalid process identifier: " + vmid);
} }
@ -137,9 +131,6 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
// protocol version // protocol version
private static final String PROTOCOL_VERSION = "1"; private static final String PROTOCOL_VERSION = "1";
// known errors
private static final int ATTACH_ERROR_BADVERSION = 101;
/** /**
* Execute the given command in the target VM. * Execute the given command in the target VM.
*/ */
@ -185,46 +176,10 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
// Create an input stream to read reply // Create an input stream to read reply
SocketInputStream sis = new SocketInputStream(s); SocketInputStreamImpl sis = new SocketInputStreamImpl(s);
// Read the command completion status // Process the command completion status
int completionStatus; processCompletionStatus(ioe, cmd, sis);
try {
completionStatus = readInt(sis);
} catch (IOException x) {
sis.close();
if (ioe != null) {
throw ioe;
} else {
throw x;
}
}
if (completionStatus != 0) {
// read from the stream and use that as the error message
String message = readErrorMessage(sis);
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")) {
String msg = "Failed to load agent library";
if (!message.isEmpty())
msg += ": " + message;
throw new AgentLoadException(msg);
} else {
if (message.isEmpty())
message = "Command failed in target VM";
throw new AttachOperationFailedException(message);
}
}
// Return the input stream so that the command output can be read // Return the input stream so that the command output can be read
return sis; return sis;
@ -233,39 +188,19 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
/* /*
* InputStream for the socket connection to get target VM * InputStream for the socket connection to get target VM
*/ */
private static class SocketInputStream extends InputStream { private static class SocketInputStreamImpl extends SocketInputStream {
int s; public SocketInputStreamImpl(long fd) {
super(fd);
public SocketInputStream(int s) {
this.s = s;
} }
public synchronized int read() throws IOException { @Override
byte b[] = new byte[1]; protected int read(long fd, byte[] bs, int off, int len) throws IOException {
int n = this.read(b, 0, 1); return VirtualMachineImpl.read((int)fd, bs, off, len);
if (n == 1) {
return b[0] & 0xff;
} else {
return -1;
}
} }
public synchronized int read(byte[] bs, int off, int len) throws IOException { @Override
if ((off < 0) || (off > bs.length) || (len < 0) || protected void close(long fd) throws IOException {
((off + len) > bs.length) || ((off + len) < 0)) { VirtualMachineImpl.close((int)fd);
throw new IndexOutOfBoundsException();
} else if (len == 0)
return 0;
return VirtualMachineImpl.read(s, bs, off, len);
}
public synchronized void close() throws IOException {
if (s != -1) {
int toClose = s;
s = -1;
VirtualMachineImpl.close(toClose);
}
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,6 @@
*/ */
package sun.tools.attach; package sun.tools.attach;
import com.sun.tools.attach.AttachOperationFailedException;
import com.sun.tools.attach.AgentLoadException; import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException; import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.spi.AttachProvider; import com.sun.tools.attach.spi.AttachProvider;
@ -58,13 +57,8 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
super(provider, vmid); super(provider, vmid);
// This provider only understands pids // This provider only understands pids
int pid; int pid = Integer.parseInt(vmid);
try { if (pid < 1) {
pid = Integer.parseInt(vmid);
if (pid < 1) {
throw new NumberFormatException();
}
} catch (NumberFormatException x) {
throw new AttachNotSupportedException("Invalid process identifier: " + vmid); throw new AttachNotSupportedException("Invalid process identifier: " + vmid);
} }
@ -141,9 +135,6 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
// protocol version // protocol version
private static final String PROTOCOL_VERSION = "1"; private static final String PROTOCOL_VERSION = "1";
// known errors
private static final int ATTACH_ERROR_BADVERSION = 101;
/** /**
* Execute the given command in the target VM. * Execute the given command in the target VM.
*/ */
@ -189,46 +180,10 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
// Create an input stream to read reply // Create an input stream to read reply
SocketInputStream sis = new SocketInputStream(s); SocketInputStreamImpl sis = new SocketInputStreamImpl(s);
// Read the command completion status // Process the command completion status
int completionStatus; processCompletionStatus(ioe, cmd, sis);
try {
completionStatus = readInt(sis);
} catch (IOException x) {
sis.close();
if (ioe != null) {
throw ioe;
} else {
throw x;
}
}
if (completionStatus != 0) {
// read from the stream and use that as the error message
String message = readErrorMessage(sis);
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")) {
String msg = "Failed to load agent library";
if (!message.isEmpty())
msg += ": " + message;
throw new AgentLoadException(msg);
} else {
if (message.isEmpty())
message = "Command failed in target VM";
throw new AttachOperationFailedException(message);
}
}
// Return the input stream so that the command output can be read // Return the input stream so that the command output can be read
return sis; return sis;
@ -237,40 +192,19 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
/* /*
* InputStream for the socket connection to get target VM * InputStream for the socket connection to get target VM
*/ */
private static class SocketInputStream extends InputStream { private static class SocketInputStreamImpl extends SocketInputStream {
int s = -1; public SocketInputStreamImpl(long fd) {
super(fd);
public SocketInputStream(int s) {
this.s = s;
} }
public synchronized int read() throws IOException { @Override
byte b[] = new byte[1]; protected int read(long fd, byte[] bs, int off, int len) throws IOException {
int n = this.read(b, 0, 1); return VirtualMachineImpl.read((int)fd, bs, off, len);
if (n == 1) {
return b[0] & 0xff;
} else {
return -1;
}
} }
public synchronized int read(byte[] bs, int off, int len) throws IOException { @Override
if ((off < 0) || (off > bs.length) || (len < 0) || protected void close(long fd) throws IOException {
((off + len) > bs.length) || ((off + len) < 0)) { VirtualMachineImpl.close((int)fd);
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
return VirtualMachineImpl.read(s, bs, off, len);
}
public synchronized void close() throws IOException {
if (s != -1) {
int toClose = s;
s = -1;
VirtualMachineImpl.close(toClose);
}
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,6 @@
*/ */
package sun.tools.attach; package sun.tools.attach;
import com.sun.tools.attach.AttachOperationFailedException;
import com.sun.tools.attach.AgentLoadException; import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException; import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.spi.AttachProvider; import com.sun.tools.attach.spi.AttachProvider;
@ -58,13 +57,8 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
super(provider, vmid); super(provider, vmid);
// This provider only understands pids // This provider only understands pids
int pid; int pid = Integer.parseInt(vmid);
try { if (pid < 1) {
pid = Integer.parseInt(vmid);
if (pid < 1) {
throw new NumberFormatException();
}
} catch (NumberFormatException x) {
throw new AttachNotSupportedException("Invalid process identifier: " + vmid); throw new AttachNotSupportedException("Invalid process identifier: " + vmid);
} }
@ -137,9 +131,6 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
// protocol version // protocol version
private static final String PROTOCOL_VERSION = "1"; private static final String PROTOCOL_VERSION = "1";
// known errors
private static final int ATTACH_ERROR_BADVERSION = 101;
/** /**
* Execute the given command in the target VM. * Execute the given command in the target VM.
*/ */
@ -185,46 +176,10 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
// Create an input stream to read reply // Create an input stream to read reply
SocketInputStream sis = new SocketInputStream(s); SocketInputStreamImpl sis = new SocketInputStreamImpl(s);
// Read the command completion status // Process the command completion status
int completionStatus; processCompletionStatus(ioe, cmd, sis);
try {
completionStatus = readInt(sis);
} catch (IOException x) {
sis.close();
if (ioe != null) {
throw ioe;
} else {
throw x;
}
}
if (completionStatus != 0) {
// read from the stream and use that as the error message
String message = readErrorMessage(sis);
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")) {
String msg = "Failed to load agent library";
if (!message.isEmpty())
msg += ": " + message;
throw new AgentLoadException(msg);
} else {
if (message.isEmpty())
message = "Command failed in target VM";
throw new AttachOperationFailedException(message);
}
}
// Return the input stream so that the command output can be read // Return the input stream so that the command output can be read
return sis; return sis;
@ -233,40 +188,19 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
/* /*
* InputStream for the socket connection to get target VM * InputStream for the socket connection to get target VM
*/ */
private static class SocketInputStream extends InputStream { private static class SocketInputStreamImpl extends SocketInputStream {
int s; public SocketInputStreamImpl(long fd) {
super(fd);
public SocketInputStream(int s) {
this.s = s;
} }
public synchronized int read() throws IOException { @Override
byte b[] = new byte[1]; protected int read(long fd, byte[] bs, int off, int len) throws IOException {
int n = this.read(b, 0, 1); return VirtualMachineImpl.read((int)fd, bs, off, len);
if (n == 1) {
return b[0] & 0xff;
} else {
return -1;
}
} }
public synchronized int read(byte[] bs, int off, int len) throws IOException { @Override
if ((off < 0) || (off > bs.length) || (len < 0) || protected void close(long fd) throws IOException {
((off + len) > bs.length) || ((off + len) < 0)) { VirtualMachineImpl.close((int)fd);
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
return VirtualMachineImpl.read(s, bs, off, len);
}
public synchronized void close() throws IOException {
if (s != -1) {
int toClose = s;
s = -1;
VirtualMachineImpl.close(toClose);
}
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
package sun.tools.attach; package sun.tools.attach;
import com.sun.tools.attach.AttachOperationFailedException;
import com.sun.tools.attach.AttachNotSupportedException; import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine; import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.AgentLoadException; import com.sun.tools.attach.AgentLoadException;
@ -70,7 +71,7 @@ public abstract class HotSpotVirtualMachine extends VirtualMachine {
try { try {
pid = Integer.parseInt(id); pid = Integer.parseInt(id);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new AttachNotSupportedException("Invalid process identifier"); throw new AttachNotSupportedException("Invalid process identifier: " + id);
} }
// The tool should be a different VM to the target. This check will // The tool should be a different VM to the target. This check will
@ -183,6 +184,8 @@ public abstract class HotSpotVirtualMachine extends VirtualMachine {
private static final int ATTACH_ERROR_NOTONCP = 101; private static final int ATTACH_ERROR_NOTONCP = 101;
private static final int ATTACH_ERROR_STARTFAIL = 102; private static final int ATTACH_ERROR_STARTFAIL = 102;
// known error
private static final int ATTACH_ERROR_BADVERSION = 101;
/* /*
* Send "properties" command to target VM * Send "properties" command to target VM
@ -366,6 +369,94 @@ public abstract class HotSpotVirtualMachine extends VirtualMachine {
return message.toString(); return message.toString();
} }
/*
* Utility method to process the completion status after command execution.
* If we get IOE during previous command execution, delay throwing it until
* completion status has been read.
*/
void processCompletionStatus(IOException ioe, String cmd, InputStream sis) throws AgentLoadException, IOException {
// 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) {
// read from the stream and use that as the error message
String message = readErrorMessage(sis);
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")) {
String msg = "Failed to load agent library";
if (!message.isEmpty()) {
msg += ": " + message;
}
throw new AgentLoadException(msg);
} else {
if (message.isEmpty()) {
message = "Command failed in target VM";
}
throw new AttachOperationFailedException(message);
}
}
}
/*
* InputStream for the socket connection to get target VM
*/
abstract static class SocketInputStream extends InputStream {
private long fd;
public SocketInputStream(long fd) {
this.fd = fd;
}
protected abstract int read(long fd, byte[] bs, int off, int len) throws IOException;
protected abstract void close(long fd) throws IOException;
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 read(fd, bs, off, len);
}
public synchronized void close() throws IOException {
if (fd != -1) {
long toClose = fd;
fd = -1;
close(toClose);
}
}
}
// -- attach timeout support // -- attach timeout support

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,6 @@
*/ */
package sun.tools.attach; package sun.tools.attach;
import com.sun.tools.attach.AttachOperationFailedException;
import com.sun.tools.attach.AgentLoadException; import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException; import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.spi.AttachProvider; import com.sun.tools.attach.spi.AttachProvider;
@ -33,6 +32,9 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Random; import java.util.Random;
/*
* Windows implementation of HotSpotVirtualMachine
*/
public class VirtualMachineImpl extends HotSpotVirtualMachine { public class VirtualMachineImpl extends HotSpotVirtualMachine {
// the enqueue code stub (copied into each target VM) // the enqueue code stub (copied into each target VM)
@ -45,12 +47,7 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
{ {
super(provider, id); super(provider, id);
int pid; int pid = Integer.parseInt(id);
try {
pid = Integer.parseInt(id);
} catch (NumberFormatException x) {
throw new AttachNotSupportedException("Invalid process identifier");
}
hProcess = openProcess(pid); hProcess = openProcess(pid);
// The target VM might be a pre-6.0 VM so we enqueue a "null" command // The target VM might be a pre-6.0 VM so we enqueue a "null" command
@ -108,26 +105,10 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
connectPipe(hPipe); connectPipe(hPipe);
// create an input stream for the pipe // create an input stream for the pipe
PipedInputStream in = new PipedInputStream(hPipe); SocketInputStreamImpl in = new SocketInputStreamImpl(hPipe);
// read completion status // Process the command completion status
int status = readInt(in); processCompletionStatus(null, cmd, in);
if (status != 0) {
// read from the stream and use that as the error message
String message = readErrorMessage(in);
in.close();
// special case the load command so that the right exception is thrown
if (cmd.equals("load")) {
String msg = "Failed to load agent library";
if (!message.isEmpty())
msg += ": " + message;
throw new AgentLoadException(msg);
} else {
if (message.isEmpty())
message = "Command failed in target VM";
throw new AttachOperationFailedException(message);
}
}
// return the input stream // return the input stream
return in; return in;
@ -139,40 +120,19 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
} }
// An InputStream based on a pipe to the target VM // An InputStream based on a pipe to the target VM
private static class PipedInputStream extends InputStream { private static class SocketInputStreamImpl extends SocketInputStream {
public SocketInputStreamImpl(long fd) {
private long hPipe; super(fd);
public PipedInputStream(long hPipe) {
this.hPipe = hPipe;
} }
public synchronized int read() throws IOException { @Override
byte b[] = new byte[1]; protected int read(long fd, byte[] bs, int off, int len) throws IOException {
int n = this.read(b, 0, 1); return VirtualMachineImpl.readPipe(fd, bs, off, len);
if (n == 1) {
return b[0] & 0xff;
} else {
return -1;
}
} }
public synchronized int read(byte[] bs, int off, int len) throws IOException { @Override
if ((off < 0) || (off > bs.length) || (len < 0) || protected void close(long fd) throws IOException {
((off + len) > bs.length) || ((off + len) < 0)) { VirtualMachineImpl.closePipe(fd);
throw new IndexOutOfBoundsException();
} else if (len == 0)
return 0;
return VirtualMachineImpl.readPipe(hPipe, bs, off, len);
}
public synchronized void close() throws IOException {
if (hPipe != -1) {
long toClose = hPipe;
hPipe = -1;
VirtualMachineImpl.closePipe(toClose);
}
} }
} }