Path: blob/master/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java
40942 views
/*1* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package sun.tools.attach;2526import com.sun.tools.attach.AttachOperationFailedException;27import com.sun.tools.attach.AgentLoadException;28import com.sun.tools.attach.AttachNotSupportedException;29import com.sun.tools.attach.spi.AttachProvider;3031import sun.tools.attach.HotSpotVirtualMachine;3233import java.io.IOException;34import java.io.InputStream;35import java.util.Random;3637public class VirtualMachineImpl extends HotSpotVirtualMachine {3839// the enqueue code stub (copied into each target VM)40private static byte[] stub;4142private volatile long hProcess; // handle to the process4344VirtualMachineImpl(AttachProvider provider, String id)45throws AttachNotSupportedException, IOException46{47super(provider, id);4849int pid;50try {51pid = Integer.parseInt(id);52} catch (NumberFormatException x) {53throw new AttachNotSupportedException("Invalid process identifier");54}55hProcess = openProcess(pid);5657// The target VM might be a pre-6.0 VM so we enqueue a "null" command58// which minimally tests that the enqueue function exists in the target59// VM.60try {61enqueue(hProcess, stub, null, null);62} catch (IOException x) {63throw new AttachNotSupportedException(x.getMessage());64}65}6667public void detach() throws IOException {68synchronized (this) {69if (hProcess != -1) {70closeProcess(hProcess);71hProcess = -1;72}73}74}7576InputStream execute(String cmd, Object ... args)77throws AgentLoadException, IOException78{79assert args.length <= 3; // includes null8081// create a pipe using a random name82Random rnd = new Random();83int r = rnd.nextInt();84String pipeprefix = "\\\\.\\pipe\\javatool";85String pipename = pipeprefix + r;86long hPipe;87try {88hPipe = createPipe(pipename);89} catch (IOException ce) {90// Retry with another random pipe name.91r = rnd.nextInt();92pipename = pipeprefix + r;93hPipe = createPipe(pipename);94}9596// check if we are detached - in theory it's possible that detach is invoked97// after this check but before we enqueue the command.98if (hProcess == -1) {99closePipe(hPipe);100throw new IOException("Detached from target VM");101}102103try {104// enqueue the command to the process105enqueue(hProcess, stub, cmd, pipename, args);106107// wait for command to complete - process will connect with the108// completion status109connectPipe(hPipe);110111// create an input stream for the pipe112PipedInputStream in = new PipedInputStream(hPipe);113114// read completion status115int status = readInt(in);116if (status != 0) {117// read from the stream and use that as the error message118String message = readErrorMessage(in);119in.close();120// special case the load command so that the right exception is thrown121if (cmd.equals("load")) {122String msg = "Failed to load agent library";123if (!message.isEmpty())124msg += ": " + message;125throw new AgentLoadException(msg);126} else {127if (message.isEmpty())128message = "Command failed in target VM";129throw new AttachOperationFailedException(message);130}131}132133// return the input stream134return in;135136} catch (IOException ioe) {137closePipe(hPipe);138throw ioe;139}140}141142// An InputStream based on a pipe to the target VM143private class PipedInputStream extends InputStream {144145private long hPipe;146147public PipedInputStream(long hPipe) {148this.hPipe = hPipe;149}150151public synchronized int read() throws IOException {152byte b[] = new byte[1];153int n = this.read(b, 0, 1);154if (n == 1) {155return b[0] & 0xff;156} else {157return -1;158}159}160161public synchronized int read(byte[] bs, int off, int len) throws IOException {162if ((off < 0) || (off > bs.length) || (len < 0) ||163((off + len) > bs.length) || ((off + len) < 0)) {164throw new IndexOutOfBoundsException();165} else if (len == 0)166return 0;167168return VirtualMachineImpl.readPipe(hPipe, bs, off, len);169}170171public synchronized void close() throws IOException {172if (hPipe != -1) {173long toClose = hPipe;174hPipe = -1;175VirtualMachineImpl.closePipe(toClose);176}177}178}179180181//-- native methods182183static native void init();184185static native byte[] generateStub();186187static native long openProcess(int pid) throws IOException;188189static native void closeProcess(long hProcess) throws IOException;190191static native long createPipe(String name) throws IOException;192193static native void closePipe(long hPipe) throws IOException;194195static native void connectPipe(long hPipe) throws IOException;196197static native int readPipe(long hPipe, byte buf[], int off, int buflen) throws IOException;198199static native void enqueue(long hProcess, byte[] stub,200String cmd, String pipename, Object ... args) throws IOException;201202static {203System.loadLibrary("attach");204init(); // native initialization205stub = generateStub(); // generate stub to copy into target process206}207}208209210