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.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -25,7 +25,6 @@
*/
package sun.tools.attach;
import com.sun.tools.attach.AttachOperationFailedException;
import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.spi.AttachProvider;
@ -57,13 +56,8 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
super(provider, vmid);
// This provider only understands pids
int pid;
try {
pid = Integer.parseInt(vmid);
if (pid < 1) {
throw new NumberFormatException();
}
} catch (NumberFormatException x) {
int pid = Integer.parseInt(vmid);
if (pid < 1) {
throw new AttachNotSupportedException("Invalid process identifier: " + vmid);
}
@ -137,9 +131,6 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
// protocol version
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.
*/
@ -185,46 +176,10 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
// Create an input stream to read reply
SocketInputStream sis = new SocketInputStream(s);
SocketInputStreamImpl sis = new SocketInputStreamImpl(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) {
// 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);
}
}
// Process the command completion status
processCompletionStatus(ioe, cmd, sis);
// Return the input stream so that the command output can be read
return sis;
@ -233,39 +188,19 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
/*
* InputStream for the socket connection to get target VM
*/
private static class SocketInputStream extends InputStream {
int s;
public SocketInputStream(int s) {
this.s = s;
private static class SocketInputStreamImpl extends SocketInputStream {
public SocketInputStreamImpl(long fd) {
super(fd);
}
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;
}
@Override
protected int read(long fd, byte[] bs, int off, int len) throws IOException {
return VirtualMachineImpl.read((int)fd, bs, off, len);
}
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 VirtualMachineImpl.read(s, bs, off, len);
}
public synchronized void close() throws IOException {
if (s != -1) {
int toClose = s;
s = -1;
VirtualMachineImpl.close(toClose);
}
@Override
protected void close(long fd) throws IOException {
VirtualMachineImpl.close((int)fd);
}
}

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.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,6 @@
*/
package sun.tools.attach;
import com.sun.tools.attach.AttachOperationFailedException;
import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.spi.AttachProvider;
@ -58,13 +57,8 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
super(provider, vmid);
// This provider only understands pids
int pid;
try {
pid = Integer.parseInt(vmid);
if (pid < 1) {
throw new NumberFormatException();
}
} catch (NumberFormatException x) {
int pid = Integer.parseInt(vmid);
if (pid < 1) {
throw new AttachNotSupportedException("Invalid process identifier: " + vmid);
}
@ -141,9 +135,6 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
// protocol version
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.
*/
@ -189,46 +180,10 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
// Create an input stream to read reply
SocketInputStream sis = new SocketInputStream(s);
SocketInputStreamImpl sis = new SocketInputStreamImpl(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) {
// 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);
}
}
// Process the command completion status
processCompletionStatus(ioe, cmd, sis);
// Return the input stream so that the command output can be read
return sis;
@ -237,40 +192,19 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
/*
* InputStream for the socket connection to get target VM
*/
private static class SocketInputStream extends InputStream {
int s = -1;
public SocketInputStream(int s) {
this.s = s;
private static class SocketInputStreamImpl extends SocketInputStream {
public SocketInputStreamImpl(long fd) {
super(fd);
}
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;
}
@Override
protected int read(long fd, byte[] bs, int off, int len) throws IOException {
return VirtualMachineImpl.read((int)fd, bs, off, len);
}
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 VirtualMachineImpl.read(s, bs, off, len);
}
public synchronized void close() throws IOException {
if (s != -1) {
int toClose = s;
s = -1;
VirtualMachineImpl.close(toClose);
}
@Override
protected void close(long fd) throws IOException {
VirtualMachineImpl.close((int)fd);
}
}

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.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,6 @@
*/
package sun.tools.attach;
import com.sun.tools.attach.AttachOperationFailedException;
import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.spi.AttachProvider;
@ -58,13 +57,8 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
super(provider, vmid);
// This provider only understands pids
int pid;
try {
pid = Integer.parseInt(vmid);
if (pid < 1) {
throw new NumberFormatException();
}
} catch (NumberFormatException x) {
int pid = Integer.parseInt(vmid);
if (pid < 1) {
throw new AttachNotSupportedException("Invalid process identifier: " + vmid);
}
@ -137,9 +131,6 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
// protocol version
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.
*/
@ -185,46 +176,10 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
// Create an input stream to read reply
SocketInputStream sis = new SocketInputStream(s);
SocketInputStreamImpl sis = new SocketInputStreamImpl(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) {
// 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);
}
}
// Process the command completion status
processCompletionStatus(ioe, cmd, sis);
// Return the input stream so that the command output can be read
return sis;
@ -233,40 +188,19 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
/*
* InputStream for the socket connection to get target VM
*/
private static class SocketInputStream extends InputStream {
int s;
public SocketInputStream(int s) {
this.s = s;
private static class SocketInputStreamImpl extends SocketInputStream {
public SocketInputStreamImpl(long fd) {
super(fd);
}
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;
}
@Override
protected int read(long fd, byte[] bs, int off, int len) throws IOException {
return VirtualMachineImpl.read((int)fd, bs, off, len);
}
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 VirtualMachineImpl.read(s, bs, off, len);
}
public synchronized void close() throws IOException {
if (s != -1) {
int toClose = s;
s = -1;
VirtualMachineImpl.close(toClose);
}
@Override
protected void close(long fd) throws IOException {
VirtualMachineImpl.close((int)fd);
}
}

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.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
package sun.tools.attach;
import com.sun.tools.attach.AttachOperationFailedException;
import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.AgentLoadException;
@ -70,7 +71,7 @@ public abstract class HotSpotVirtualMachine extends VirtualMachine {
try {
pid = Integer.parseInt(id);
} 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
@ -183,6 +184,8 @@ public abstract class HotSpotVirtualMachine extends VirtualMachine {
private static final int ATTACH_ERROR_NOTONCP = 101;
private static final int ATTACH_ERROR_STARTFAIL = 102;
// known error
private static final int ATTACH_ERROR_BADVERSION = 101;
/*
* Send "properties" command to target VM
@ -366,6 +369,94 @@ public abstract class HotSpotVirtualMachine extends VirtualMachine {
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

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.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,6 @@
*/
package sun.tools.attach;
import com.sun.tools.attach.AttachOperationFailedException;
import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.spi.AttachProvider;
@ -33,6 +32,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
/*
* Windows implementation of HotSpotVirtualMachine
*/
public class VirtualMachineImpl extends HotSpotVirtualMachine {
// the enqueue code stub (copied into each target VM)
@ -45,12 +47,7 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
{
super(provider, id);
int pid;
try {
pid = Integer.parseInt(id);
} catch (NumberFormatException x) {
throw new AttachNotSupportedException("Invalid process identifier");
}
int pid = Integer.parseInt(id);
hProcess = openProcess(pid);
// 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);
// create an input stream for the pipe
PipedInputStream in = new PipedInputStream(hPipe);
SocketInputStreamImpl in = new SocketInputStreamImpl(hPipe);
// read completion status
int status = readInt(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);
}
}
// Process the command completion status
processCompletionStatus(null, cmd, in);
// return the input stream
return in;
@ -139,40 +120,19 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
}
// An InputStream based on a pipe to the target VM
private static class PipedInputStream extends InputStream {
private long hPipe;
public PipedInputStream(long hPipe) {
this.hPipe = hPipe;
private static class SocketInputStreamImpl extends SocketInputStream {
public SocketInputStreamImpl(long fd) {
super(fd);
}
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;
}
@Override
protected int read(long fd, byte[] bs, int off, int len) throws IOException {
return VirtualMachineImpl.readPipe(fd, bs, off, len);
}
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 VirtualMachineImpl.readPipe(hPipe, bs, off, len);
}
public synchronized void close() throws IOException {
if (hPipe != -1) {
long toClose = hPipe;
hPipe = -1;
VirtualMachineImpl.closePipe(toClose);
}
@Override
protected void close(long fd) throws IOException {
VirtualMachineImpl.closePipe(fd);
}
}