8039173: Propagate errors from Diagnostic Commands as exceptions in the attach framework
authorsla
Fri, 09 May 2014 12:06:13 +0200
changeset 24363 33b869a8806b
parent 24362 c4ce2234c96e
child 24364 da8afb112f5d
8039173: Propagate errors from Diagnostic Commands as exceptions in the attach framework Reviewed-by: igerasim, alanb, dsamersoff
jdk/src/share/classes/com/sun/tools/attach/AttachOperationFailedException.java
jdk/src/share/classes/com/sun/tools/attach/VirtualMachine.java
jdk/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java
jdk/src/share/classes/sun/tools/jcmd/JCmd.java
jdk/src/solaris/classes/sun/tools/attach/BsdVirtualMachine.java
jdk/src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java
jdk/src/solaris/classes/sun/tools/attach/SolarisVirtualMachine.java
jdk/src/solaris/native/sun/tools/attach/BsdVirtualMachine.c
jdk/src/solaris/native/sun/tools/attach/LinuxVirtualMachine.c
jdk/src/solaris/native/sun/tools/attach/SolarisVirtualMachine.c
jdk/src/windows/classes/sun/tools/attach/WindowsVirtualMachine.java
jdk/src/windows/native/sun/tools/attach/WindowsVirtualMachine.c
jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/tools/attach/AttachOperationFailedException.java	Fri May 09 12:06:13 2014 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, 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 com.sun.tools.attach;
+
+import java.io.IOException;
+
+/**
+ * Exception type to signal that an attach operation failed in the target VM.
+ *
+ * <p> This exception can be thrown by the various operations of
+ * {@link com.sun.tools.attach.VirtualMachine} when the operation
+ * fails in the target VM. If there is a communication error,
+ * a regular IOException will be thrown.
+ *
+ * @since 1.9
+ */
+@jdk.Exported
+public class AttachOperationFailedException extends IOException {
+
+    private static final long serialVersionUID = 2140308168167478043L;
+
+    /**
+     * Constructs an <code>AttachOperationFailedException</code> with
+     * the specified detail message.
+     *
+     * @param   s   the detail message.
+     */
+    public AttachOperationFailedException(String message) {
+        super(message);
+    }
+}
--- a/jdk/src/share/classes/com/sun/tools/attach/VirtualMachine.java	Fri May 09 09:47:07 2014 +0100
+++ b/jdk/src/share/classes/com/sun/tools/attach/VirtualMachine.java	Fri May 09 12:06:13 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, 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
@@ -564,8 +564,15 @@
      *
      * @return  The system properties
      *
+     * @throws  AttachOperationFailedException
+     *          If the target virtual machine is unable to complete the
+     *          attach operation. A more specific error message will be
+     *          given by {@link AttachOperationFailedException#getMessage()}.
+     *
      * @throws  IOException
-     *          If an I/O error occurs
+     *          If an I/O error occurs, a communication error for example,
+     *          that cannot be identified as an error to indicate that the
+     *          operation failed in the target VM.
      *
      * @see     java.lang.System#getProperties
      * @see     #loadAgentLibrary
@@ -591,8 +598,15 @@
      *
      * @return       The agent properties
      *
+     * @throws       AttachOperationFailedException
+     *               If the target virtual machine is unable to complete the
+     *               attach operation. A more specific error message will be
+     *               given by {@link AttachOperationFailedException#getMessage()}.
+     *
      * @throws       IOException
-     *               If an I/O error occurs
+     *               If an I/O error occurs, a communication error for example,
+     *               that cannot be identified as an error to indicate that the
+     *               operation failed in the target VM.
      */
     public abstract Properties getAgentProperties() throws IOException;
 
--- a/jdk/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java	Fri May 09 09:47:07 2014 +0100
+++ b/jdk/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java	Fri May 09 12:06:13 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, 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
@@ -257,6 +257,20 @@
         return value;
     }
 
+    /*
+     * Utility method to read data into a String.
+     */
+    String readErrorMessage(InputStream sis) throws IOException {
+        byte b[] = new byte[1024];
+        int n;
+        StringBuffer message = new StringBuffer();
+        while ((n = sis.read(b)) != -1) {
+            message.append(new String(b, 0, n, "UTF-8"));
+        }
+        return message.toString();
+    }
+
+
     // -- attach timeout support
 
     private static long defaultAttachTimeout = 5000;
--- a/jdk/src/share/classes/sun/tools/jcmd/JCmd.java	Fri May 09 09:47:07 2014 +0100
+++ b/jdk/src/share/classes/sun/tools/jcmd/JCmd.java	Fri May 09 12:06:13 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2014, 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
@@ -33,10 +33,12 @@
 import java.util.Comparator;
 import java.net.URISyntaxException;
 
+import com.sun.tools.attach.AttachOperationFailedException;
 import com.sun.tools.attach.VirtualMachine;
 import com.sun.tools.attach.VirtualMachineDescriptor;
 import com.sun.tools.attach.AgentLoadException;
 import com.sun.tools.attach.AttachNotSupportedException;
+
 import sun.tools.attach.HotSpotVirtualMachine;
 import sun.tools.jstat.JStatLogger;
 import sun.jvmstat.monitor.Monitor;
@@ -119,6 +121,7 @@
             pids.add(arg.getPid() + "");
         }
 
+        boolean success = true;
         for (String pid : pids) {
             System.out.println(pid + ":");
             if (arg.isListCounters()) {
@@ -126,11 +129,16 @@
             } else {
                 try {
                     executeCommandForPid(pid, arg.getCommand());
+                } catch(AttachOperationFailedException ex) {
+                    System.err.println(ex.getMessage());
+                    success = false;
                 } catch(Exception ex) {
                     ex.printStackTrace();
+                    success = false;
                 }
             }
         }
+        System.exit(success ? 0 : 1);
     }
 
     private static void executeCommandForPid(String pid, String command)
@@ -150,13 +158,18 @@
                 // read to EOF and just print output
                 byte b[] = new byte[256];
                 int n;
+                boolean messagePrinted = false;
                 do {
                     n = in.read(b);
                     if (n > 0) {
                         String s = new String(b, 0, n, "UTF-8");
                         System.out.print(s);
+                        messagePrinted = true;
                     }
                 } while (n > 0);
+                if (!messagePrinted) {
+                    System.out.println("Command executed successfully");
+                }
             }
         }
         vm.detach();
--- a/jdk/src/solaris/classes/sun/tools/attach/BsdVirtualMachine.java	Fri May 09 09:47:07 2014 +0100
+++ b/jdk/src/solaris/classes/sun/tools/attach/BsdVirtualMachine.java	Fri May 09 12:06:13 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, 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,14 +24,14 @@
  */
 package sun.tools.attach;
 
-import com.sun.tools.attach.VirtualMachine;
+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;
+
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.File;
-import java.util.Properties;
 
 /*
  * Bsd implementation of HotSpotVirtualMachine
@@ -191,6 +191,8 @@
         }
 
         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
@@ -205,7 +207,11 @@
             if (cmd.equals("load")) {
                 throw new AgentLoadException("Failed to load agent library");
             } else {
-                throw new IOException("Command failed in target VM");
+                if (message == null) {
+                    throw new AttachOperationFailedException("Command failed in target VM");
+                } else {
+                    throw new AttachOperationFailedException(message);
+                }
             }
         }
 
@@ -237,8 +243,9 @@
             if ((off < 0) || (off > bs.length) || (len < 0) ||
                 ((off + len) > bs.length) || ((off + len) < 0)) {
                 throw new IndexOutOfBoundsException();
-            } else if (len == 0)
+            } else if (len == 0) {
                 return 0;
+            }
 
             return BsdVirtualMachine.read(s, bs, off, len);
         }
--- a/jdk/src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java	Fri May 09 09:47:07 2014 +0100
+++ b/jdk/src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java	Fri May 09 12:06:13 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, 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,14 +24,14 @@
  */
 package sun.tools.attach;
 
-import com.sun.tools.attach.VirtualMachine;
+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;
+
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.File;
-import java.util.Properties;
 
 /*
  * Linux implementation of HotSpotVirtualMachine
@@ -207,6 +207,8 @@
         }
 
         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
@@ -221,7 +223,11 @@
             if (cmd.equals("load")) {
                 throw new AgentLoadException("Failed to load agent library");
             } else {
-                throw new IOException("Command failed in target VM");
+                if (message == null) {
+                    throw new AttachOperationFailedException("Command failed in target VM");
+                } else {
+                    throw new AttachOperationFailedException(message);
+                }
             }
         }
 
--- a/jdk/src/solaris/classes/sun/tools/attach/SolarisVirtualMachine.java	Fri May 09 09:47:07 2014 +0100
+++ b/jdk/src/solaris/classes/sun/tools/attach/SolarisVirtualMachine.java	Fri May 09 12:06:13 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, 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,15 +24,15 @@
  */
 package sun.tools.attach;
 
-import com.sun.tools.attach.VirtualMachine;
+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;
+
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.File;
 import java.io.FileNotFoundException;
-import java.util.Properties;
 
 /*
  * Solaris implementation of HotSpotVirtualMachine.
@@ -147,11 +147,17 @@
         // If non-0 it means an error but we need to special-case the
         // "load" command to ensure that the right exception is thrown.
         if (completionStatus != 0) {
+            // read from the stream and use that as the error message
+            String message = readErrorMessage(sis);
             sis.close();
             if (cmd.equals("load")) {
                 throw new AgentLoadException("Failed to load agent library");
             } else {
-                throw new IOException("Command failed in target VM");
+                if (message == null) {
+                    throw new AttachOperationFailedException("Command failed in target VM");
+                } else {
+                    throw new AttachOperationFailedException(message);
+                }
             }
         }
 
--- a/jdk/src/solaris/native/sun/tools/attach/BsdVirtualMachine.c	Fri May 09 09:47:07 2014 +0100
+++ b/jdk/src/solaris/native/sun/tools/attach/BsdVirtualMachine.c	Fri May 09 12:06:13 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, 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
@@ -200,14 +200,14 @@
         len = remaining;
     }
 
-    RESTARTABLE(read(fd, buf+off, len), n);
+    RESTARTABLE(read(fd, buf, len), n);
     if (n == -1) {
         JNU_ThrowIOExceptionWithLastError(env, "read");
     } else {
         if (n == 0) {
             n = -1;     // EOF
         } else {
-            (*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf+off));
+            (*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf));
         }
     }
     return n;
--- a/jdk/src/solaris/native/sun/tools/attach/LinuxVirtualMachine.c	Fri May 09 09:47:07 2014 +0100
+++ b/jdk/src/solaris/native/sun/tools/attach/LinuxVirtualMachine.c	Fri May 09 12:06:13 2014 +0200
@@ -418,14 +418,14 @@
         len = remaining;
     }
 
-    RESTARTABLE(read(fd, buf+off, len), n);
+    RESTARTABLE(read(fd, buf, len), n);
     if (n == -1) {
         JNU_ThrowIOExceptionWithLastError(env, "read");
     } else {
         if (n == 0) {
             n = -1;     // EOF
         } else {
-            (*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf+off));
+            (*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf));
         }
     }
     return n;
--- a/jdk/src/solaris/native/sun/tools/attach/SolarisVirtualMachine.c	Fri May 09 09:47:07 2014 +0100
+++ b/jdk/src/solaris/native/sun/tools/attach/SolarisVirtualMachine.c	Fri May 09 12:06:13 2014 +0200
@@ -1,5 +1,5 @@
-/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+''/*
+ * Copyright (c) 2005, 2014, 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
@@ -161,14 +161,14 @@
         len = remaining;
     }
 
-    RESTARTABLE(read(fd, buf+off, len), n);
+    RESTARTABLE(read(fd, buf, len), n);
     if (n == -1) {
         JNU_ThrowIOExceptionWithLastError(env, "read");
     } else {
         if (n == 0) {
             n = -1;     // EOF
         } else {
-            (*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf+off));
+            (*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf));
         }
     }
     return n;
--- a/jdk/src/windows/classes/sun/tools/attach/WindowsVirtualMachine.java	Fri May 09 09:47:07 2014 +0100
+++ b/jdk/src/windows/classes/sun/tools/attach/WindowsVirtualMachine.java	Fri May 09 12:06:13 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, 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,15 +24,15 @@
  */
 package sun.tools.attach;
 
-import com.sun.tools.attach.VirtualMachine;
+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;
+
 import sun.tools.attach.HotSpotVirtualMachine;
+
 import java.io.IOException;
-import java.io.File;
 import java.io.InputStream;
-import java.util.Properties;
 import java.util.Random;
 
 public class WindowsVirtualMachine extends HotSpotVirtualMachine {
@@ -105,11 +105,17 @@
             // read completion status
             int status = readInt(is);
             if (status != 0) {
+                // read from the stream and use that as the error message
+                String message = readErrorMessage(is);
                 // 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");
+                    if (message == null) {
+                        throw new AttachOperationFailedException("Command failed in target VM");
+                    } else {
+                        throw new AttachOperationFailedException(message);
+                    }
                 }
             }
 
--- a/jdk/src/windows/native/sun/tools/attach/WindowsVirtualMachine.c	Fri May 09 09:47:07 2014 +0100
+++ b/jdk/src/windows/native/sun/tools/attach/WindowsVirtualMachine.c	Fri May 09 12:06:13 2014 +0200
@@ -343,7 +343,7 @@
         if (nread == 0) {
             return (jint)-1;        // EOF
         } else {
-            (*env)->SetByteArrayRegion(env, ba, off, (jint)nread, (jbyte *)(buf+off));
+            (*env)->SetByteArrayRegion(env, ba, off, (jint)nread, (jbyte *)(buf));
         }
     }
 
--- a/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java	Fri May 09 09:47:07 2014 +0100
+++ b/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java	Fri May 09 12:06:13 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, 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
@@ -616,7 +616,7 @@
             final boolean[] checks = new boolean[3];
             jcmd(
                 line -> {
-                    if (line.equals("java.lang.RuntimeException: Invalid agent state")) {
+                    if (line.contains("java.lang.RuntimeException: Invalid agent state")) {
                         checks[0] = true;
                     }
                 },
@@ -627,7 +627,7 @@
 
             jcmd(
                 line -> {
-                    if (line.equals("java.lang.RuntimeException: Invalid agent state")) {
+                    if (line.contains("java.lang.RuntimeException: Invalid agent state")) {
                         checks[1] = true;
                     }
                 },