changeset 58423:d6ae5212211f

8238268: Many SA tests are not running on OSX because they do not attempt to use sudo when available Reviewed-by: sspitsyn, iignatyev
author cjplummer
date Tue, 17 Mar 2020 18:04:59 -0700
parents dd9eb63b5d3e
children 824e6b7c5bcf
files test/hotspot/jtreg/TEST.ROOT test/hotspot/jtreg/compiler/ciReplay/TestSAClient.java test/hotspot/jtreg/compiler/ciReplay/TestSAServer.java test/hotspot/jtreg/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java test/hotspot/jtreg/resourcehogs/serviceability/sa/TestHeapDumpForLargeArray.java test/hotspot/jtreg/serviceability/sa/CDSJMapClstats.java test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java test/hotspot/jtreg/serviceability/sa/DeadlockDetectionTest.java test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java test/hotspot/jtreg/serviceability/sa/TestClassDump.java test/hotspot/jtreg/serviceability/sa/TestClhsdbJstackLock.java test/hotspot/jtreg/serviceability/sa/TestCpoolForInvokeDynamic.java test/hotspot/jtreg/serviceability/sa/TestDefaultMethods.java test/hotspot/jtreg/serviceability/sa/TestG1HeapRegion.java test/hotspot/jtreg/serviceability/sa/TestHeapDumpForInvokeDynamic.java test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSize.java test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSizeForInterface.java test/hotspot/jtreg/serviceability/sa/TestIntConstant.java test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixed.java test/hotspot/jtreg/serviceability/sa/TestPrintMdo.java test/hotspot/jtreg/serviceability/sa/TestRevPtrsForInvokeDynamic.java test/hotspot/jtreg/serviceability/sa/TestType.java test/hotspot/jtreg/serviceability/sa/TestUniverse.java test/hotspot/jtreg/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdConnectTest.java test/hotspot/jtreg/serviceability/sa/sadebugd/SADebugDTest.java test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java test/jdk/TEST.ROOT test/jdk/sun/tools/jhsdb/BasicLauncherTest.java test/jdk/sun/tools/jhsdb/HeapDumpTest.java test/jdk/sun/tools/jhsdb/HeapDumpTestWithActiveProcess.java test/jdk/sun/tools/jhsdb/JShellHeapDumpTest.java test/jdk/sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java test/jdk/sun/tools/jhsdb/heapconfig/TmtoolTestScenario.java test/jdk/sun/tools/jstack/DeadlockDetectionTest.java test/jtreg-ext/requires/VMProps.java test/lib/jdk/test/lib/Platform.java test/lib/jdk/test/lib/SA/SATestUtils.java
diffstat 41 files changed, 329 insertions(+), 281 deletions(-) [+]
line wrap: on
line diff
--- a/test/hotspot/jtreg/TEST.ROOT	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/TEST.ROOT	Tue Mar 17 18:04:59 2020 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2020, 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
@@ -55,7 +55,6 @@
     vm.cpu.features \
     vm.debug \
     vm.hasSA \
-    vm.hasSAandCanAttach \
     vm.hasJFR \
     vm.rtm.cpu \
     vm.rtm.compiler \
--- a/test/hotspot/jtreg/compiler/ciReplay/TestSAClient.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/compiler/ciReplay/TestSAClient.java	Tue Mar 17 18:04:59 2020 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2020, 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
@@ -26,7 +26,7 @@
  * @bug 8011675
  * @library / /test/lib
  * @summary testing of ciReplay with using generated by SA replay.txt
- * @requires vm.hasSAandCanAttach & vm.flightRecorder != true & vm.compMode != "Xint" & vm.debug == true & vm.flavor == "client"
+ * @requires vm.hasSA & vm.flightRecorder != true & vm.compMode != "Xint" & vm.debug == true & vm.flavor == "client"
  * @modules java.base/jdk.internal.misc
  * @build sun.hotspot.WhiteBox
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
--- a/test/hotspot/jtreg/compiler/ciReplay/TestSAServer.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/compiler/ciReplay/TestSAServer.java	Tue Mar 17 18:04:59 2020 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2020, 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
@@ -26,7 +26,7 @@
  * @bug 8011675
  * @library / /test/lib
  * @summary testing of ciReplay with using generated by SA replay.txt
- * @requires vm.hasSAandCanAttach & vm.flightRecorder != true & vm.compMode != "Xint" & vm.debug == true & vm.flavor == "server"
+ * @requires vm.hasSA & vm.flightRecorder != true & vm.compMode != "Xint" & vm.debug == true & vm.flavor == "server"
  * @modules java.base/jdk.internal.misc
  * @build sun.hotspot.WhiteBox
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
--- a/test/hotspot/jtreg/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java	Tue Mar 17 18:04:59 2020 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2020, 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
@@ -27,7 +27,7 @@
  * @test CompressedClassSpaceSizeInJmapHeap
  * @bug 8004924
  * @summary Checks that jmap -heap contains the flag CompressedClassSpaceSize
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @requires vm.bits == 64 & vm.opt.final.UseCompressedOops == true
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
@@ -39,6 +39,7 @@
 import jdk.test.lib.Platform;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.SA.SATestUtils;
 import java.nio.file.*;
 import java.io.File;
 import java.nio.charset.Charset;
@@ -47,6 +48,8 @@
 public class CompressedClassSpaceSizeInJmapHeap {
     // Note that on some platforms it may require root privileges to run this test.
     public static void main(String[] args) throws Exception {
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
+
         if (!Platform.is64bit()) {
             // Compressed Class Space is only available on 64-bit JVMs
             return;
@@ -59,7 +62,7 @@
                                               .addToolArg("--heap")
                                               .addToolArg("--pid")
                                               .addToolArg(pid);
-        ProcessBuilder pb = new ProcessBuilder(jmap.getCommand());
+        ProcessBuilder pb = SATestUtils.createProcessBuilder(jmap);
 
         File out = new File("CompressedClassSpaceSizeInJmapHeap.stdout.txt");
         pb.redirectOutput(out);
--- a/test/hotspot/jtreg/resourcehogs/serviceability/sa/TestHeapDumpForLargeArray.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/resourcehogs/serviceability/sa/TestHeapDumpForLargeArray.java	Tue Mar 17 18:04:59 2020 -0700
@@ -34,19 +34,20 @@
 import sun.jvm.hotspot.debugger.*;
 
 import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.Asserts;
 import jdk.test.lib.JDKToolLauncher;
 import jdk.test.lib.JDKToolFinder;
 import jdk.test.lib.Platform;
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.SA.SATestUtils;
 import jdk.test.lib.Utils;
-import jdk.test.lib.Asserts;
 
 /**
  * @test
  * @library /test/lib
  * @bug 8171084
- * @requires vm.hasSAandCanAttach & (vm.bits == "64" & os.maxMemory > 8g)
+ * @requires vm.hasSA & (vm.bits == "64" & os.maxMemory > 8g)
  * @modules java.base/jdk.internal.misc
  *          jdk.hotspot.agent/sun.jvm.hotspot
  *          jdk.hotspot.agent/sun.jvm.hotspot.utilities
@@ -70,8 +71,7 @@
         launcher.addToolArg("--pid");
         launcher.addToolArg(Long.toString(lingeredAppPid));
 
-        ProcessBuilder processBuilder = new ProcessBuilder();
-        processBuilder.command(launcher.getCommand());
+        ProcessBuilder processBuilder = SATestUtils.createProcessBuilder(launcher);
         System.out.println(
             processBuilder.command().stream().collect(Collectors.joining(" ")));
 
@@ -86,6 +86,7 @@
     }
 
     public static void main (String... args) throws Exception {
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
 
         String heapDumpFileName = "LargeArrayHeapDump.bin";
 
--- a/test/hotspot/jtreg/serviceability/sa/CDSJMapClstats.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/CDSJMapClstats.java	Tue Mar 17 18:04:59 2020 -0700
@@ -25,7 +25,7 @@
  * @test
  * @bug 8204308
  * @summary Test the jhsdb jmap -clstats command with CDS enabled
- * @requires vm.hasSAandCanAttach & vm.cds
+ * @requires vm.hasSA & vm.cds
  * @library /test/lib
  * @run main/othervm/timeout=2400 CDSJMapClstats
  */
@@ -39,6 +39,7 @@
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.SA.SATestUtils;
 
 public class CDSJMapClstats {
 
@@ -50,8 +51,7 @@
         launcher.addToolArg("--pid");
         launcher.addToolArg(Long.toString(lingeredAppPid));
 
-        ProcessBuilder processBuilder = new ProcessBuilder();
-        processBuilder.command(launcher.getCommand());
+        ProcessBuilder processBuilder = SATestUtils.createProcessBuilder(launcher);
         System.out.println(
             processBuilder.command().stream().collect(Collectors.joining(" ")));
 
@@ -64,6 +64,7 @@
 
     public static void main(String[] args) throws Exception {
         System.out.println("Starting CDSJMapClstats test");
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         String sharedArchiveName = "ArchiveForCDSJMapClstats.jsa";
         LingeredApp theApp = null;
 
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java	Tue Mar 17 18:04:59 2020 -0700
@@ -68,36 +68,32 @@
             // the 'jstack -v' command
             cmds = new ArrayList<String>();
 
-            // Output could be null if the test was skipped due to
-            // attach permission issues.
-            if (output != null) {
-                String cmdStr = null;
-                String[] parts = output.split("LingeredAppWithTrivialMain.main");
-                String[] tokens = parts[1].split(" ");
-                for (String token : tokens) {
-                    if (token.contains("pc")) {
-                        String[] address = token.split("=");
-                        // address[1] represents the address of the Method
-                        cmdStr = "findpc " + address[1].replace(",","");
-                        cmds.add(cmdStr);
-                        break;
-                    }
+            String cmdStr = null;
+            String[] parts = output.split("LingeredAppWithTrivialMain.main");
+            String[] tokens = parts[1].split(" ");
+            for (String token : tokens) {
+                if (token.contains("pc")) {
+                    String[] address = token.split("=");
+                    // address[1] represents the address of the Method
+                    cmdStr = "findpc " + address[1].replace(",","");
+                    cmds.add(cmdStr);
+                    break;
                 }
+            }
 
-                Map<String, List<String>> expStrMap = new HashMap<>();
-                if (withXcomp) {
-                    expStrMap.put(cmdStr, List.of(
+            Map<String, List<String>> expStrMap = new HashMap<>();
+            if (withXcomp) {
+                expStrMap.put(cmdStr, List.of(
                             "In code in NMethod for LingeredAppWithTrivialMain.main",
                             "content:",
                             "oops:",
                             "frame size:"));
-                } else {
-                    expStrMap.put(cmdStr, List.of(
+            } else {
+                expStrMap.put(cmdStr, List.of(
                             "In interpreter codelet"));
-                }
+            }
 
-                test.run(theApp.getPid(), cmds, expStrMap, null);
-            }
+            test.run(theApp.getPid(), cmds, expStrMap, null);
         } catch (SkippedException se) {
             throw se;
         } catch (Exception ex) {
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java	Tue Mar 17 18:04:59 2020 -0700
@@ -30,6 +30,7 @@
 import java.util.stream.Collectors;
 
 import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.SA.SATestUtils;
 import jdk.test.lib.Utils;
 import jdk.test.lib.apps.LingeredApp;
 import jdk.test.lib.process.OutputAnalyzer;
@@ -37,7 +38,7 @@
 /**
  * @test
  * @bug 8196969
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @library /test/lib
  * @run main/othervm ClhsdbJstackXcompStress
  */
@@ -63,8 +64,7 @@
             launcher.addToolArg("--pid");
             launcher.addToolArg(Long.toString(app.getPid()));
 
-            ProcessBuilder pb = new ProcessBuilder();
-            pb.command(launcher.getCommand());
+            ProcessBuilder pb = SATestUtils.createProcessBuilder(launcher);
             Process jhsdb = pb.start();
             OutputAnalyzer out = new OutputAnalyzer(jhsdb);
 
@@ -88,6 +88,7 @@
     }
 
     public static void main(String... args) throws Exception {
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         LingeredApp app = null;
         try {
             app = new LingeredAppWithRecComputation();
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java	Tue Mar 17 18:04:59 2020 -0700
@@ -33,8 +33,6 @@
 import jdk.test.lib.JDKToolFinder;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.SA.SATestUtils;
-import jtreg.SkippedException;
-
 
 /**
  * This is a framework to run 'jhsdb clhsdb' commands.
@@ -45,11 +43,9 @@
 public class ClhsdbLauncher {
 
     private Process toolProcess;
-    private boolean needPrivileges;
 
     public ClhsdbLauncher() {
         toolProcess = null;
-        needPrivileges = false;
     }
 
     /**
@@ -66,11 +62,7 @@
             System.out.println("Starting clhsdb against " + lingeredAppPid);
         }
 
-        List<String> cmdStringList = Arrays.asList(launcher.getCommand());
-        if (needPrivileges) {
-            cmdStringList = SATestUtils.addPrivileges(cmdStringList);
-        }
-        ProcessBuilder processBuilder = new ProcessBuilder(cmdStringList);
+        ProcessBuilder processBuilder = SATestUtils.createProcessBuilder(launcher);
         toolProcess = processBuilder.start();
     }
 
@@ -203,22 +195,7 @@
                       Map<String, List<String>> unExpectedStrMap)
         throws Exception {
 
-        if (!Platform.shouldSAAttach()) {
-            if (Platform.isOSX()) {
-                if (Platform.isSignedOSX()) {
-                    throw new SkippedException("SA attach not expected to work. JDK is signed.");
-                } else if (SATestUtils.canAddPrivileges()) {
-                    needPrivileges = true;
-                }
-            }
-            if (!needPrivileges)  {
-               // Skip the test if we don't have enough permissions to attach
-               // and cannot add privileges.
-               throw new SkippedException(
-                   "SA attach not expected to work. Insufficient privileges.");
-           }
-        }
-
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         attach(lingeredAppPid);
         return runCmd(commands, expectedStrMap, unExpectedStrMap);
     }
--- a/test/hotspot/jtreg/serviceability/sa/DeadlockDetectionTest.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/DeadlockDetectionTest.java	Tue Mar 17 18:04:59 2020 -0700
@@ -24,8 +24,7 @@
 /**
  * @test
  * @summary Test deadlock detection
- * @requires vm.hasSAandCanAttach
- * @requires os.family != "mac"
+ * @requires vm.hasSA
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  * @modules java.management
@@ -38,18 +37,17 @@
 
 import jdk.test.lib.apps.LingeredApp;
 import jdk.test.lib.apps.LingeredAppWithDeadlock;
-
-import jdk.test.lib.Utils;
 import jdk.test.lib.JDKToolLauncher;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.SA.SATestUtils;
+import jdk.test.lib.Utils;
 
 import jtreg.SkippedException;
 
 public class DeadlockDetectionTest {
 
     private static LingeredAppWithDeadlock theApp = null;
-    private static ProcessBuilder processBuilder = new ProcessBuilder();
 
     private static OutputAnalyzer jstack(String... toolArgs) throws Exception {
         JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");
@@ -60,7 +58,7 @@
             }
         }
 
-        processBuilder.command(launcher.getCommand());
+        ProcessBuilder processBuilder = SATestUtils.createProcessBuilder(launcher);
         System.out.println(processBuilder.command().stream().collect(Collectors.joining(" ")));
         OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
         System.out.println(output.getOutput());
@@ -69,6 +67,7 @@
     }
 
     public static void main(String[] args) throws Exception {
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         System.out.println("Starting DeadlockDetectionTest");
 
         if (!LingeredApp.isLastModifiedWorking()) {
@@ -91,7 +90,6 @@
                 output.shouldHaveExitValue(0);
                 output.shouldContain("Found a total of 1 deadlock.");
             }
-
         } finally {
             LingeredApp.stopApp(theApp);
         }
--- a/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java	Tue Mar 17 18:04:59 2020 -0700
@@ -30,18 +30,19 @@
 import jdk.test.lib.JDKToolLauncher;
 import jdk.test.lib.Platform;
 import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.SA.SATestUtils;
 import jdk.test.lib.Utils;
 
 /**
  * @test
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @library /test/lib
  * @run main JhsdbThreadInfoTest
  */
 public class JhsdbThreadInfoTest {
 
     public static void main(String[] args) throws Exception {
-
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         LingeredApp app = null;
 
         try {
@@ -54,8 +55,7 @@
             jhsdbLauncher.addToolArg("--pid");
             jhsdbLauncher.addToolArg(Long.toString(app.getPid()));
 
-            ProcessBuilder pb = new ProcessBuilder();
-            pb.command(jhsdbLauncher.getCommand());
+            ProcessBuilder pb = SATestUtils.createProcessBuilder(jhsdbLauncher);
             Process jhsdb = pb.start();
 
             OutputAnalyzer out = new OutputAnalyzer(jhsdb);
--- a/test/hotspot/jtreg/serviceability/sa/TestClassDump.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/TestClassDump.java	Tue Mar 17 18:04:59 2020 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2020, 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
@@ -29,12 +29,13 @@
 import jdk.test.lib.Platform;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.SA.SATestUtils;
 
 /**
  * @test
  * @bug 8184982
  * @summary Test ClassDump tool
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @library /test/lib
  * @run main/othervm TestClassDump
  */
@@ -50,6 +51,7 @@
         pb = ProcessTools.createJavaProcessBuilder(
                 "-Dsun.jvm.hotspot.tools.jcore.outputDir=jtreg_classes",
                 "-m", "jdk.hotspot.agent/sun.jvm.hotspot.tools.jcore.ClassDump", String.valueOf(lingeredAppPid));
+        SATestUtils.addPrivilegesIfNeeded(pb);
         output = new OutputAnalyzer(pb.start());
         output.shouldHaveExitValue(0);
         if (!Files.isDirectory(Paths.get("jtreg_classes"))) {
@@ -69,6 +71,7 @@
                 "-Dsun.jvm.hotspot.tools.jcore.outputDir=jtreg_classes2",
                 "-Dsun.jvm.hotspot.tools.jcore.PackageNameFilter.pkgList=jdk,sun",
                 "-m", "jdk.hotspot.agent/sun.jvm.hotspot.tools.jcore.ClassDump", String.valueOf(lingeredAppPid));
+        SATestUtils.addPrivilegesIfNeeded(pb);
         output = new OutputAnalyzer(pb.start());
         output.shouldHaveExitValue(0);
         if (Files.exists(Paths.get("jtreg_classes2", "java", "math", "BigInteger.class"))) {
@@ -83,6 +86,7 @@
     }
 
     public static void main(String[] args) throws Exception {
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         LingeredApp theApp = null;
         try {
             theApp = LingeredApp.startApp();
--- a/test/hotspot/jtreg/serviceability/sa/TestClhsdbJstackLock.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/TestClhsdbJstackLock.java	Tue Mar 17 18:04:59 2020 -0700
@@ -31,7 +31,7 @@
 
 /**
  * @test
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @library /test/lib
  * @run main/othervm TestClhsdbJstackLock
  */
--- a/test/hotspot/jtreg/serviceability/sa/TestCpoolForInvokeDynamic.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/TestCpoolForInvokeDynamic.java	Tue Mar 17 18:04:59 2020 -0700
@@ -33,18 +33,19 @@
 import sun.jvm.hotspot.ui.classbrowser.HTMLGenerator;
 
 import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.Asserts;
 import jdk.test.lib.JDKToolLauncher;
 import jdk.test.lib.JDKToolFinder;
 import jdk.test.lib.Platform;
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.SA.SATestUtils;
 import jdk.test.lib.Utils;
-import jdk.test.lib.Asserts;
 
 /**
  * @test
  * @library /test/lib
- * @requires vm.hasSAandCanAttach & os.family != "mac"
+ * @requires vm.hasSA
  * @modules java.base/jdk.internal.misc
  *          jdk.hotspot.agent/sun.jvm.hotspot
  *          jdk.hotspot.agent/sun.jvm.hotspot.utilities
@@ -103,6 +104,7 @@
 
         // Start a new process to attach to the lingered app
         ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(toolArgs);
+        SATestUtils.addPrivilegesIfNeeded(processBuilder);
         OutputAnalyzer SAOutput = ProcessTools.executeProcess(processBuilder);
         SAOutput.shouldHaveExitValue(0);
         System.out.println(SAOutput.getOutput());
@@ -115,6 +117,7 @@
     }
 
     public static void main (String... args) throws Exception {
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
 
         String[] instanceKlassNames = new String[] {
                                           "LingeredAppWithInvokeDynamic"
--- a/test/hotspot/jtreg/serviceability/sa/TestDefaultMethods.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/TestDefaultMethods.java	Tue Mar 17 18:04:59 2020 -0700
@@ -32,18 +32,19 @@
 import sun.jvm.hotspot.utilities.MethodArray;
 
 import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.Asserts;
 import jdk.test.lib.JDKToolLauncher;
 import jdk.test.lib.JDKToolFinder;
 import jdk.test.lib.Platform;
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.SA.SATestUtils;
 import jdk.test.lib.Utils;
-import jdk.test.lib.Asserts;
 
 /**
  * @test
  * @library /test/lib
- * @requires vm.hasSAandCanAttach & os.family != "mac"
+ * @requires vm.hasSA
  * @modules java.base/jdk.internal.misc
  *          jdk.hotspot.agent/sun.jvm.hotspot
  *          jdk.hotspot.agent/sun.jvm.hotspot.utilities
@@ -109,6 +110,7 @@
 
         // Start a new process to attach to the lingered app
         ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(toolArgs);
+        SATestUtils.addPrivilegesIfNeeded(processBuilder);
         OutputAnalyzer SAOutput = ProcessTools.executeProcess(processBuilder);
         SAOutput.shouldHaveExitValue(0);
         System.out.println(SAOutput.getOutput());
@@ -124,7 +126,7 @@
     }
 
     public static void main (String... args) throws Exception {
-
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         String[] instanceKlassNames = new String[] {
                                           "Language",
                                           "ParselTongue",
--- a/test/hotspot/jtreg/serviceability/sa/TestG1HeapRegion.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/TestG1HeapRegion.java	Tue Mar 17 18:04:59 2020 -0700
@@ -34,12 +34,13 @@
 import jdk.test.lib.Platform;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.SA.SATestUtils;
 import jdk.test.lib.Utils;
 
 /**
  * @test
  * @library /test/lib
- * @requires vm.hasSAandCanAttach & os.family != "mac"
+ * @requires vm.hasSA
  * @requires vm.gc.G1
  * @modules jdk.hotspot.agent/sun.jvm.hotspot
  *          jdk.hotspot.agent/sun.jvm.hotspot.gc.g1
@@ -82,12 +83,14 @@
 
         // Start a new process to attach to the lingered app
         ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(toolArgs);
+        SATestUtils.addPrivilegesIfNeeded(processBuilder);
         OutputAnalyzer SAOutput = ProcessTools.executeProcess(processBuilder);
         SAOutput.shouldHaveExitValue(0);
         System.out.println(SAOutput.getOutput());
     }
 
     public static void main (String... args) throws Exception {
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         if (args == null || args.length == 0) {
             try {
                 String[] vmArgs = Utils.appendTestJavaOpts(
--- a/test/hotspot/jtreg/serviceability/sa/TestHeapDumpForInvokeDynamic.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/TestHeapDumpForInvokeDynamic.java	Tue Mar 17 18:04:59 2020 -0700
@@ -34,13 +34,14 @@
 import sun.jvm.hotspot.debugger.*;
 
 import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.Asserts;
 import jdk.test.lib.JDKToolLauncher;
 import jdk.test.lib.JDKToolFinder;
 import jdk.test.lib.Platform;
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.SA.SATestUtils;
 import jdk.test.lib.Utils;
-import jdk.test.lib.Asserts;
 import jdk.test.lib.hprof.HprofParser;
 import jdk.test.lib.hprof.parser.HprofReader;
 import jdk.test.lib.hprof.parser.PositionDataInputStream;
@@ -49,7 +50,7 @@
 /**
  * @test
  * @library /test/lib
- * @requires vm.hasSAandCanAttach & os.family != "mac"
+ * @requires vm.hasSA
  * @modules java.base/jdk.internal.misc
  *          jdk.hotspot.agent/sun.jvm.hotspot
  *          jdk.hotspot.agent/sun.jvm.hotspot.utilities
@@ -97,8 +98,7 @@
         launcher.addToolArg("--pid");
         launcher.addToolArg(Long.toString(lingeredAppPid));
 
-        ProcessBuilder processBuilder = new ProcessBuilder();
-        processBuilder.command(launcher.getCommand());
+        ProcessBuilder processBuilder = SATestUtils.createProcessBuilder(launcher);
         System.out.println(
             processBuilder.command().stream().collect(Collectors.joining(" ")));
 
@@ -112,7 +112,7 @@
     }
 
     public static void main (String... args) throws Exception {
-
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         String heapDumpFileName = "lambdaHeapDump.bin";
 
         File heapDumpFile = new File(heapDumpFileName);
--- a/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSize.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSize.java	Tue Mar 17 18:04:59 2020 -0700
@@ -30,13 +30,14 @@
 import java.util.List;
 import java.util.stream.Collectors;
 
+import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.Asserts;
 import jdk.test.lib.JDKToolLauncher;
 import jdk.test.lib.Platform;
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.SA.SATestUtils;
 import jdk.test.lib.Utils;
-import jdk.test.lib.apps.LingeredApp;
-import jdk.test.lib.Asserts;
 
 import java.io.*;
 import java.util.*;
@@ -44,7 +45,7 @@
 /**
  * @test
  * @library /test/lib
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @modules java.base/jdk.internal.misc
  *          jdk.hotspot.agent/sun.jvm.hotspot
  *          jdk.hotspot.agent/sun.jvm.hotspot.utilities
@@ -97,6 +98,7 @@
 
             ProcessBuilder processBuilder = ProcessTools
                                             .createJavaProcessBuilder(toolArgs);
+            SATestUtils.addPrivilegesIfNeeded(processBuilder);
             output = ProcessTools.executeProcess(processBuilder);
             System.out.println(output.getOutput());
             output.shouldHaveExitValue(0);
@@ -148,7 +150,7 @@
     }
 
     public static void main(String[] args) throws Exception {
-
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         if (args == null || args.length == 0) {
             System.out.println ("No args run. Starting with args now.");
             startMeWithArgs();
--- a/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSizeForInterface.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSizeForInterface.java	Tue Mar 17 18:04:59 2020 -0700
@@ -29,18 +29,19 @@
 import sun.jvm.hotspot.debugger.*;
 
 import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.Asserts;
 import jdk.test.lib.JDKToolLauncher;
 import jdk.test.lib.JDKToolFinder;
 import jdk.test.lib.Platform;
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.SA.SATestUtils;
 import jdk.test.lib.Utils;
-import jdk.test.lib.Asserts;
 
 /**
  * @test
  * @library /test/lib
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @modules java.base/jdk.internal.misc
  *          jdk.hotspot.agent/sun.jvm.hotspot
  *          jdk.hotspot.agent/sun.jvm.hotspot.utilities
@@ -118,6 +119,7 @@
         // Start a new process to attach to the LingeredApp process to get SA info
         ProcessBuilder processBuilder = ProcessTools
                   .createJavaProcessBuilder(toolArgs);
+        SATestUtils.addPrivilegesIfNeeded(processBuilder);
         OutputAnalyzer SAOutput = ProcessTools.executeProcess(processBuilder);
         SAOutput.shouldHaveExitValue(0);
         System.out.println(SAOutput.getOutput());
@@ -141,6 +143,7 @@
     }
 
     public static void main (String... args) throws Exception {
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         String[] instanceKlassNames = new String[] {
                                           "Language",
                                           "ParselTongue",
--- a/test/hotspot/jtreg/serviceability/sa/TestIntConstant.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/TestIntConstant.java	Tue Mar 17 18:04:59 2020 -0700
@@ -33,7 +33,7 @@
  * @test
  * @summary Test the 'intConstant' command of jhsdb clhsdb.
  * @bug 8190307
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @library /test/lib
  * @build jdk.test.lib.apps.*
  * @run main/othervm TestIntConstant
--- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java	Tue Mar 17 18:04:59 2020 -0700
@@ -35,11 +35,12 @@
 import jdk.test.lib.Platform;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.SA.SATestUtils;
 import jdk.test.lib.Utils;
 
 /**
  * @test
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @library /test/lib
  * @run main/othervm TestJhsdbJstackLock
  */
@@ -47,7 +48,7 @@
 public class TestJhsdbJstackLock {
 
     public static void main (String... args) throws Exception {
-
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         LingeredApp app = null;
 
         try {
@@ -60,8 +61,7 @@
             launcher.addToolArg("--pid");
             launcher.addToolArg(Long.toString(app.getPid()));
 
-            ProcessBuilder pb = new ProcessBuilder();
-            pb.command(launcher.getCommand());
+            ProcessBuilder pb = SATestUtils.createProcessBuilder(launcher);
             Process jhsdb = pb.start();
             OutputAnalyzer out = new OutputAnalyzer(jhsdb);
 
--- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixed.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixed.java	Tue Mar 17 18:04:59 2020 -0700
@@ -27,6 +27,7 @@
 import java.util.regex.Pattern;
 
 import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.SA.SATestUtils;
 import jdk.test.lib.Utils;
 import jdk.test.lib.apps.LingeredApp;
 import jdk.test.lib.process.OutputAnalyzer;
@@ -34,7 +35,7 @@
 /**
  * @test
  * @bug 8208091
- * @requires (os.family == "linux") & (vm.hasSAandCanAttach)
+ * @requires (os.family == "linux") & (vm.hasSA)
  * @library /test/lib
  * @run main/othervm TestJhsdbJstackMixed
  */
@@ -135,8 +136,7 @@
             launcher.addToolArg("--pid");
             launcher.addToolArg(Long.toString(app.getPid()));
 
-            ProcessBuilder pb = new ProcessBuilder();
-            pb.command(launcher.getCommand());
+            ProcessBuilder pb = SATestUtils.createProcessBuilder(launcher);
             Process jhsdb = pb.start();
             OutputAnalyzer out = new OutputAnalyzer(jhsdb);
 
@@ -161,7 +161,7 @@
     }
 
     public static void main(String... args) throws Exception {
-
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         LingeredApp app = null;
 
         try {
--- a/test/hotspot/jtreg/serviceability/sa/TestPrintMdo.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/TestPrintMdo.java	Tue Mar 17 18:04:59 2020 -0700
@@ -32,7 +32,7 @@
 /**
  * @test
  * @library /test/lib
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @requires vm.flavor == "server" & !vm.emulatedClient & !(vm.opt.TieredStopAtLevel == 1)
  * @build jdk.test.lib.apps.*
  * @run main/othervm TestPrintMdo
@@ -41,7 +41,6 @@
 public class TestPrintMdo {
 
     public static void main (String... args) throws Exception {
-
         System.out.println("Starting TestPrintMdo test");
         LingeredApp app = null;
         try {
--- a/test/hotspot/jtreg/serviceability/sa/TestRevPtrsForInvokeDynamic.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/TestRevPtrsForInvokeDynamic.java	Tue Mar 17 18:04:59 2020 -0700
@@ -34,12 +34,13 @@
 import jdk.test.lib.Platform;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.SA.SATestUtils;
 import jdk.test.lib.Utils;
 
 /**
  * @test
  * @library /test/lib
- * @requires vm.hasSAandCanAttach & os.family != "mac"
+ * @requires vm.hasSA
  * @modules java.base/jdk.internal.misc
  *          jdk.hotspot.agent/sun.jvm.hotspot
  *          jdk.hotspot.agent/sun.jvm.hotspot.utilities
@@ -74,12 +75,14 @@
 
         // Start a new process to attach to the lingered app
         ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(toolArgs);
+        SATestUtils.addPrivilegesIfNeeded(processBuilder);
         OutputAnalyzer SAOutput = ProcessTools.executeProcess(processBuilder);
         SAOutput.shouldHaveExitValue(0);
         System.out.println(SAOutput.getOutput());
     }
 
     public static void main (String... args) throws Exception {
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         if (args == null || args.length == 0) {
             try {
                 String[] vmArgs = Utils.appendTestJavaOpts("-XX:+UsePerfData");
--- a/test/hotspot/jtreg/serviceability/sa/TestType.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/TestType.java	Tue Mar 17 18:04:59 2020 -0700
@@ -33,7 +33,7 @@
  * @test
  * @summary Test the 'type' command of jhsdb clhsdb.
  * @bug 8190307
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @library /test/lib
  * @build jdk.test.lib.apps.*
  * @run main/othervm TestType
--- a/test/hotspot/jtreg/serviceability/sa/TestUniverse.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/TestUniverse.java	Tue Mar 17 18:04:59 2020 -0700
@@ -34,7 +34,7 @@
 /**
  * @test
  * @summary Test the 'universe' command of jhsdb clhsdb.
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @bug 8190307
  * @library /test/lib
  * @build jdk.test.lib.apps.*
--- a/test/hotspot/jtreg/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java	Tue Mar 17 18:04:59 2020 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2020, 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
@@ -36,12 +36,13 @@
 import jdk.test.lib.Platform;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.SA.SATestUtils;
 
 /**
  * @test
  * @bug 6313383
  * @key regression
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @summary Regression test for hprof export issue due to large heaps (>2G)
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
@@ -59,6 +60,7 @@
     private static final long G = 1024L * M;
 
     public static void main(String[] args) throws Exception {
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
 
         // All heap dumps should create 1.0.2 file format
         testHProfFileFormat("-Xmx1g", 22 * M, HPROF_HEADER_1_0_2);
@@ -101,8 +103,7 @@
             jMapLauncher.addToolArg("--pid");
             jMapLauncher.addToolArg(String.valueOf(pid));
 
-            ProcessBuilder jMapProcessBuilder = new ProcessBuilder(
-                    jMapLauncher.getCommand());
+            ProcessBuilder jMapProcessBuilder = SATestUtils.createProcessBuilder(jMapLauncher);
             System.out.println("jmap command: "
                     + Arrays.toString(jMapLauncher.getCommand()));
 
--- a/test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdConnectTest.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdConnectTest.java	Tue Mar 17 18:04:59 2020 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2020, 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,7 +25,7 @@
  * @test
  * @bug 8209790
  * @summary Checks ability for connecting to debug server (jstack, jmap, jinfo, jsnap)
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @requires os.family != "windows"
  * @modules java.base/jdk.internal.misc
  * @library /test/lib
@@ -36,6 +36,7 @@
 import java.io.IOException;
 
 import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.SA.SATestUtils;
 import jdk.test.lib.apps.LingeredApp;
 import jdk.test.lib.process.OutputAnalyzer;
 
@@ -52,7 +53,7 @@
             jhsdbLauncher.addToolArg("localhost");
         }
 
-        Process jhsdb = (new ProcessBuilder(jhsdbLauncher.getCommand())).start();
+        Process jhsdb = (SATestUtils.createProcessBuilder(jhsdbLauncher)).start();
         OutputAnalyzer out = new OutputAnalyzer(jhsdb);
 
         jhsdb.waitFor();
@@ -110,6 +111,7 @@
     }
 
     public static void main(String[] args) throws Exception {
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         LingeredApp app = null;
 
         try {
--- a/test/hotspot/jtreg/serviceability/sa/sadebugd/SADebugDTest.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/sadebugd/SADebugDTest.java	Tue Mar 17 18:04:59 2020 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2020, 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
@@ -26,7 +26,7 @@
  * @bug 8163805 8224252
  * @summary Checks that the jshdb debugd utility sucessfully starts
  *          and tries to attach to a running process
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @requires os.family != "windows"
  * @modules java.base/jdk.internal.misc
  * @library /test/lib
@@ -38,13 +38,30 @@
 
 import jdk.test.lib.apps.LingeredApp;
 import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.SA.SATestUtils;
 import static jdk.test.lib.process.ProcessTools.startProcess;
 
+import jtreg.SkippedException;
+
 public class SADebugDTest {
 
     private static final String GOLDEN = "Debugger attached";
 
     public static void main(String[] args) throws Exception {
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
+
+        if (SATestUtils.needsPrivileges()) {
+            // This tests has issues if you try adding privileges on OSX. The debugd process cannot
+            // be killed if you do this (because it is a root process and the test is not), so the destroy()
+            // call fails to do anything, and then waitFor() will time out. If you try to manually kill it with
+            // a "sudo kill" command, that seems to work, but then leaves the LingeredApp it was
+            // attached to in a stuck state for some unknown reason, causing the stopApp() call
+            // to timeout. For that reason we don't run this test when privileges are needed. Note
+            // it does appear to run fine as root, so we still allow it to run on OSX when privileges
+            // are not required.
+            throw new SkippedException("Cannot run this test on OSX if adding privileges is required.");
+        }
+
         LingeredApp app = null;
 
         try {
@@ -55,11 +72,11 @@
             jhsdbLauncher.addToolArg("debugd");
             jhsdbLauncher.addToolArg("--pid");
             jhsdbLauncher.addToolArg(Long.toString(app.getPid()));
-            ProcessBuilder pb = new ProcessBuilder(jhsdbLauncher.getCommand());
+            ProcessBuilder pb = SATestUtils.createProcessBuilder(jhsdbLauncher);
 
             // The startProcess will block untl the 'golden' string appears in either process' stdout or stderr
             // In case of timeout startProcess kills the debugd process
-            Process debugd = startProcess("debugd", pb, null, l -> l.contains(GOLDEN), 0, TimeUnit.SECONDS);
+            Process debugd = startProcess("debugd", pb, null, l -> l.contains(GOLDEN), 20, TimeUnit.SECONDS);
 
             // If we are here, this means we have received the golden line and the test has passed
             // The debugd remains running, we have to kill it
--- a/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java	Tue Mar 17 18:04:59 2020 -0700
@@ -51,7 +51,7 @@
         VM_TYPE("isClient", "isServer", "isMinimal", "isZero", "isEmbedded"),
         MODE("isInt", "isMixed", "isComp"),
         IGNORED("isEmulatedClient", "isDebugBuild", "isFastDebugBuild",
-                "isSlowDebugBuild", "hasSA", "shouldSAAttach", "isTieredSupported",
+                "isSlowDebugBuild", "hasSA", "isRoot", "isTieredSupported",
                 "areCustomLoadersSupportedForCDS", "isDefaultCDSArchiveSupported",
                 "isSignedOSX");
 
--- a/test/jdk/TEST.ROOT	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/jdk/TEST.ROOT	Tue Mar 17 18:04:59 2020 -0700
@@ -53,7 +53,6 @@
     vm.cds \
     vm.debug \
     vm.hasSA \
-    vm.hasSAandCanAttach \
     vm.hasJFR \
     docker.support \
     release.implementor
--- a/test/jdk/sun/tools/jhsdb/BasicLauncherTest.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/jdk/sun/tools/jhsdb/BasicLauncherTest.java	Tue Mar 17 18:04:59 2020 -0700
@@ -25,7 +25,7 @@
  * @test
  * @summary Basic test for jhsdb launcher
  * @library /test/lib
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @build jdk.test.lib.apps.*
  * @run main BasicLauncherTest
  */
@@ -43,6 +43,7 @@
 import jdk.test.lib.apps.LingeredApp;
 import jdk.test.lib.Platform;
 import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.SA.SATestUtils;
 import jdk.test.lib.Utils;
 
 public class BasicLauncherTest {
@@ -78,7 +79,7 @@
             launcher.addToolArg("clhsdb");
             launcher.addToolArg("--pid=" + Long.toString(theApp.getPid()));
 
-            ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
+            ProcessBuilder processBuilder = SATestUtils.createProcessBuilder(launcher);
             processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
             Process toolProcess = processBuilder.start();
 
@@ -122,13 +123,6 @@
     }
 
     public static void launchJStack() throws IOException {
-
-        if (Platform.isOSX()) {
-            // Coredump stackwalking is not implemented for Darwin
-            System.out.println("This test is not expected to work on OS X. Skipping");
-            return;
-        }
-
         System.out.println("Starting LingeredApp");
         try {
             theApp = LingeredApp.startApp("-Xmx256m");
@@ -139,7 +133,7 @@
             launcher.addToolArg("jstack");
             launcher.addToolArg("--pid=" + Long.toString(theApp.getPid()));
 
-            ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
+            ProcessBuilder processBuilder = SATestUtils.createProcessBuilder(launcher);
             OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);;
             output.shouldContain("No deadlocks found");
             output.shouldNotContain("illegal bci");
@@ -175,7 +169,7 @@
 
             launcher.addToolArg("--pid=" + Long.toString(theApp.getPid()));
 
-            ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
+            ProcessBuilder processBuilder = SATestUtils.createProcessBuilder(launcher);
             processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
             OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);;
             output.shouldContain(expectedMessage);
@@ -198,6 +192,7 @@
     }
 
     public static void main(String[] args) throws Exception {
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
 
         launchCLHSDB();
 
--- a/test/jdk/sun/tools/jhsdb/HeapDumpTest.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/jdk/sun/tools/jhsdb/HeapDumpTest.java	Tue Mar 17 18:04:59 2020 -0700
@@ -25,7 +25,7 @@
  * @test
  * @bug 8163346
  * @summary Test hashing of extended characters in Serviceability Agent.
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @library /test/lib
  * @compile -encoding utf8 HeapDumpTest.java
  * @run main/timeout=240 HeapDumpTest
@@ -38,12 +38,12 @@
 import java.util.List;
 import java.util.Arrays;
 
-import jdk.test.lib.Platform;
+import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.hprof.parser.HprofReader;
 import jdk.test.lib.JDKToolLauncher;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.apps.LingeredApp;
-import jdk.test.lib.hprof.parser.HprofReader;
+import jdk.test.lib.SA.SATestUtils;
 
 public class HeapDumpTest {
 
@@ -72,7 +72,7 @@
 
             launcher.addToolArg("--pid=" + Long.toString(theApp.getPid()));
 
-            ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
+            ProcessBuilder processBuilder = SATestUtils.createProcessBuilder(launcher);
             processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
             OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
             System.out.println("stdout:");
@@ -125,7 +125,7 @@
     }
 
     public static void main(String[] args) throws Exception {
-
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         testHeapDump();
 
         // The test throws RuntimeException on error.
--- a/test/jdk/sun/tools/jhsdb/HeapDumpTestWithActiveProcess.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/jdk/sun/tools/jhsdb/HeapDumpTestWithActiveProcess.java	Tue Mar 17 18:04:59 2020 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2020, 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,7 @@
 /**
  * @test
  * @bug  8230731 8001227 8231635 8231634 8196969
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @library /test/lib
  * @compile JShellHeapDumpTest.java
  * @run main/timeout=240 JShellHeapDumpTest nosleep
--- a/test/jdk/sun/tools/jhsdb/JShellHeapDumpTest.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/jdk/sun/tools/jhsdb/JShellHeapDumpTest.java	Tue Mar 17 18:04:59 2020 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2020, 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,7 @@
 /**
  * @test
  * @bug 8225715
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @library /test/lib
  * @compile JShellHeapDumpTest.java
  * @run main/timeout=240 JShellHeapDumpTest
@@ -38,11 +38,12 @@
 import java.util.Arrays;
 import java.util.Map;
 
+import jdk.test.lib.hprof.parser.HprofReader;
 import jdk.test.lib.JDKToolLauncher;
 import jdk.test.lib.JDKToolFinder;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.hprof.parser.HprofReader;
+import jdk.test.lib.SA.SATestUtils;
 
 import jdk.jshell.JShell;
 
@@ -67,7 +68,7 @@
 
             launcher.addToolArg("--pid=" + Long.toString(jShellPID));
 
-            ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
+            ProcessBuilder processBuilder = SATestUtils.createProcessBuilder(launcher);
             OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
             System.out.println("jhsdb jmap stdout:");
             System.out.println(output.getStdout());
@@ -150,6 +151,7 @@
     }
 
     public static void main(String[] args) throws Exception {
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
         if (args.length == 1) {
             if (args[0].equals("nosleep")) {
                 doSleep = false;
--- a/test/jdk/sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/jdk/sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java	Tue Mar 17 18:04:59 2020 -0700
@@ -30,15 +30,15 @@
 import java.util.Map;
 
 import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.SA.SATestUtils;
 import jdk.test.lib.Utils;
-import jdk.test.lib.Platform;
 
 /**
  * @test
  * @bug 8042397
  * @summary Unit test for jmap utility test heap configuration reader
  *
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @library /test/lib
  * @modules java.management
  *          jdk.hotspot.agent/sun.jvm.hotspot
@@ -120,6 +120,7 @@
 
     public static void main(String[] args) throws Exception {
         System.out.println("Starting JMapHeapConfigTest");
+        SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
 
         if (!LingeredApp.isLastModifiedWorking()) {
             // Exact behaviour of the test depends to operating system and the test nature,
--- a/test/jdk/sun/tools/jhsdb/heapconfig/TmtoolTestScenario.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/jdk/sun/tools/jhsdb/heapconfig/TmtoolTestScenario.java	Tue Mar 17 18:04:59 2020 -0700
@@ -35,6 +35,7 @@
 
 import jdk.test.lib.apps.LingeredApp;
 import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.SA.SATestUtils;
 import jdk.test.lib.Utils;
 
 public class TmtoolTestScenario {
@@ -110,8 +111,8 @@
                 launcher.addToolArg("--pid");
                 launcher.addToolArg(Long.toString(theApp.getPid()));
 
-                ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
-                processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
+                ProcessBuilder processBuilder = SATestUtils.createProcessBuilder(launcher);
+               processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
                 Process toolProcess = processBuilder.start();
 
                 // By default child process output stream redirected to pipe, so we are reading it in foreground.
--- a/test/jdk/sun/tools/jstack/DeadlockDetectionTest.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/jdk/sun/tools/jstack/DeadlockDetectionTest.java	Tue Mar 17 18:04:59 2020 -0700
@@ -27,19 +27,19 @@
 
 import jdk.test.lib.apps.LingeredApp;
 import jdk.test.lib.apps.LingeredAppWithDeadlock;
-import jdk.test.lib.Platform;
+import jdk.test.lib.JDKToolLauncher;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.Utils;
 
-import jdk.test.lib.Utils;
-import jdk.test.lib.JDKToolLauncher;
+import jtreg.SkippedException;
 
 /**
  * @test
  * @summary Test deadlock detection
- * @requires vm.hasSAandCanAttach
+ * @requires vm.hasSA
  * @library /test/lib
- * @build jdk.test.lib.apps.* jdk.test.lib.Platform
+ * @build jdk.test.lib.apps.*
  * @build DeadlockDetectionTest
  * @run main DeadlockDetectionTest
  */
@@ -83,13 +83,11 @@
             System.out.println(output.getOutput());
 
             if (output.getExitValue() == 3) {
-                System.out.println("Test can't run for some reason. Skipping");
-            }
-            else {
+                throw new SkippedException("Test can't run for some reason");
+            } else {
                 output.shouldHaveExitValue(0);
                 output.shouldContain("Found 1 deadlock.");
             }
-
         } finally {
             LingeredApp.stopApp(theApp);
         }
--- a/test/jtreg-ext/requires/VMProps.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/jtreg-ext/requires/VMProps.java	Tue Mar 17 18:04:59 2020 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2020, 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
@@ -96,9 +96,6 @@
         // vm.hasSA is "true" if the VM contains the serviceability agent
         // and jhsdb.
         map.put("vm.hasSA", this::vmHasSA);
-        // vm.hasSAandCanAttach is "true" if the VM contains the serviceability agent
-        // and jhsdb and it can attach to the VM.
-        map.put("vm.hasSAandCanAttach", this::vmHasSAandCanAttach);
         // vm.hasJFR is "true" if JFR is included in the build of the VM and
         // so tests can be executed.
         map.put("vm.hasJFR", this::vmHasJFR);
@@ -319,19 +316,6 @@
     }
 
     /**
-     * @return "true" if VM has a serviceability agent and it can
-     * attach to the VM.
-     */
-    protected String vmHasSAandCanAttach() {
-        try {
-            return "" + Platform.shouldSAAttach();
-        } catch (IOException e) {
-            e.printStackTrace();
-            return errorWithMessage("Checking whether SA can attach to the VM failed.:" + e);
-        }
-    }
-
-    /**
      * @return "true" if the VM is compiled with Java Flight Recorder (JFR)
      * support.
      */
--- a/test/lib/jdk/test/lib/Platform.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/lib/jdk/test/lib/Platform.java	Tue Mar 17 18:04:59 2020 -0700
@@ -26,15 +26,12 @@
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.io.RandomAccessFile;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Pattern;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
 
 public class Platform {
     public  static final String vmName      = privilegedGetProperty("java.vm.name");
@@ -217,6 +214,10 @@
         return osArch;
     }
 
+    public static boolean isRoot() {
+        return userName.equals("root");
+    }
+
     /**
      * Return a boolean for whether SA and jhsdb are ported/available
      * on this platform.
@@ -286,77 +287,6 @@
         }
     }
 
-    /**
-     * Return a boolean for whether we expect to be able to attach
-     * the SA to our own processes on this system.  This requires
-     * that SA is ported/available on this platform.
-     */
-    public static boolean shouldSAAttach() throws IOException {
-        if (!hasSA()) return false;
-        if (isLinux()) {
-            return canPtraceAttachLinux();
-        } else if (isOSX()) {
-            return canAttachOSX() && !isSignedOSX();
-        } else {
-            // Other platforms expected to work:
-            return true;
-        }
-    }
-
-    /**
-     * On Linux, first check the SELinux boolean "deny_ptrace" and return false
-     * as we expect to be denied if that is "1".  Then expect permission to attach
-     * if we are root, so return true.  Then return false for an expected denial
-     * if "ptrace_scope" is 1, and true otherwise.
-     */
-    private static boolean canPtraceAttachLinux() throws IOException {
-        // SELinux deny_ptrace:
-        File deny_ptrace = new File("/sys/fs/selinux/booleans/deny_ptrace");
-        if (deny_ptrace.exists()) {
-            try (RandomAccessFile file = AccessController.doPrivileged(
-                    (PrivilegedExceptionAction<RandomAccessFile>) () -> new RandomAccessFile(deny_ptrace, "r"))) {
-                if (file.readByte() != '0') {
-                    return false;
-                }
-            } catch (PrivilegedActionException e) {
-                IOException t = (IOException) e.getException();
-                throw t;
-            }
-        }
-
-        // YAMA enhanced security ptrace_scope:
-        // 0 - a process can PTRACE_ATTACH to any other process running under the same uid
-        // 1 - restricted ptrace: a process must be a children of the inferior or user is root
-        // 2 - only processes with CAP_SYS_PTRACE may use ptrace or user is root
-        // 3 - no attach: no processes may use ptrace with PTRACE_ATTACH
-        File ptrace_scope = new File("/proc/sys/kernel/yama/ptrace_scope");
-        if (ptrace_scope.exists()) {
-            try (RandomAccessFile file = AccessController.doPrivileged(
-                    (PrivilegedExceptionAction<RandomAccessFile>) () -> new RandomAccessFile(ptrace_scope, "r"))) {
-                byte yama_scope = file.readByte();
-                if (yama_scope == '3') {
-                    return false;
-                }
-
-                if (!userName.equals("root") && yama_scope != '0') {
-                    return false;
-                }
-            } catch (PrivilegedActionException e) {
-                IOException t = (IOException) e.getException();
-                throw t;
-            }
-        }
-        // Otherwise expect to be permitted:
-        return true;
-    }
-
-    /**
-     * On OSX, expect permission to attach only if we are root.
-     */
-    private static boolean canAttachOSX() {
-        return userName.equals("root");
-    }
-
     private static boolean isArch(String archnameRE) {
         return Pattern.compile(archnameRE, Pattern.CASE_INSENSITIVE)
                       .matcher(osArch)
--- a/test/lib/jdk/test/lib/SA/SATestUtils.java	Tue Mar 17 20:54:50 2020 -0400
+++ b/test/lib/jdk/test/lib/SA/SATestUtils.java	Tue Mar 17 18:04:59 2020 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2020, 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
@@ -26,64 +26,187 @@
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.zip.GZIPInputStream;
 
 import jdk.test.lib.Asserts;
+import jdk.test.lib.JDKToolLauncher;
 import jdk.test.lib.Platform;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
 import jtreg.SkippedException;
 
 public class SATestUtils {
+    /**
+     * Creates a ProcessBuilder, adding privileges (sudo) if needed.
+     */
+    public static ProcessBuilder createProcessBuilder(JDKToolLauncher launcher) {
+        List<String> cmdStringList = Arrays.asList(launcher.getCommand());
+        if (needsPrivileges()) {
+            cmdStringList = addPrivileges(cmdStringList);
+        }
+        return new ProcessBuilder(cmdStringList);
+    }
 
-    public static boolean canAddPrivileges()
-       throws IOException, InterruptedException {
-       List<String> echoList = new ArrayList<String>();
-       echoList.add("sudo");
-       echoList.add("-E");
-       echoList.add("/bin/echo");
-       echoList.add("'Checking for sudo'");
-       ProcessBuilder pb = new ProcessBuilder(echoList);
+    /**
+     * Checks if SA Attach is expected to work.
+     * @throws SkippedException if SA Attach is not expected to work.
+    */
+    public static void skipIfCannotAttach() {
+        if (!Platform.hasSA()) {
+            throw new SkippedException("SA not supported.");
+        }
+        try {
+            if (Platform.isLinux()) {
+                if (!canPtraceAttachLinux()) {
+                    throw new SkippedException("SA Attach not expected to work. Ptrace attach not supported.");
+                }
+            } else if (Platform.isOSX()) {
+                if (Platform.isSignedOSX()) {
+                    throw new SkippedException("SA Attach not expected to work. JDK is signed.");
+                }
+                if (!Platform.isRoot() && !canAddPrivileges()) {
+                    throw new SkippedException("SA Attach not expected to work. Insufficient privileges (not root and can't use sudo).");
+                }
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("skipIfCannotAttach() failed due to IOException.", e);
+        }
+    }
+
+    /**
+     * Returns true if this platform is expected to require extra privileges (running using sudo).
+     */
+    public static boolean needsPrivileges() {
+        return Platform.isOSX() && !Platform.isRoot();
+    }
+
+    /**
+     * Returns true if a no-password sudo is expected to work properly.
+     */
+    private static boolean canAddPrivileges()  throws IOException {
+       List<String> sudoList = new ArrayList<String>();
+       sudoList.add("sudo");
+       sudoList.add("-E"); // Preserve existing environment variables.
+       sudoList.add("-n"); // non-interactive. Don't prompt for password. Must be cached or not required.
+       sudoList.add("/bin/echo");
+       sudoList.add("'Checking for sudo'");
+       ProcessBuilder pb = new ProcessBuilder(sudoList);
        Process echoProcess = pb.start();
-       if (echoProcess.waitFor(60, TimeUnit.SECONDS) == false) {
-           // 'sudo' has been added but we don't have a no-password
-           // entry for the user in the /etc/sudoers list. Could
-           // have timed out waiting for the password. Skip the
-           // test if there is a timeout here.
-           System.out.println("Timed out waiting for the password to be entered.");
-           echoProcess.destroyForcibly();
-           return false;
+       try {
+           if (echoProcess.waitFor(60, TimeUnit.SECONDS) == false) {
+               // Due to using the "-n" option, sudo should complete almost immediately. 60 seconds
+               // is more than generous. If it didn't complete in that time, something went very wrong.
+               echoProcess.destroyForcibly();
+               throw new RuntimeException("Timed out waiting for sudo to execute.");
+           }
+       } catch (InterruptedException e) {
+           throw new RuntimeException("sudo process interrupted", e);
        }
+
        if (echoProcess.exitValue() == 0) {
            return true;
        }
        java.io.InputStream is = echoProcess.getErrorStream();
        String err = new String(is.readAllBytes());
        System.out.println(err);
-       // 'sudo' has been added but we don't have a no-password
-       // entry for the user in the /etc/sudoers list. Check for
-       // the sudo error message and skip the test.
-       if (err.contains("no tty present") ||
-           err.contains("a password is required")) {
+       // 'sudo' has been run, but did not succeed, probably because the cached credentials
+       //  have expired, or we don't have a no-password entry for the user in the /etc/sudoers list.
+       // Check the sudo error message and skip the test.
+       if (err.contains("no tty present") || err.contains("a password is required")) {
            return false;
        } else {
-           throw new Error("Unknown Error from 'sudo'");
+           throw new RuntimeException("Unknown error from 'sudo': " + err);
        }
     }
 
-    public static List<String> addPrivileges(List<String> cmdStringList)
-        throws IOException {
-        Asserts.assertTrue(Platform.isOSX());
+    /**
+     * Adds privileges (sudo) to the command.
+     */
+    private static List<String> addPrivileges(List<String> cmdStringList) {
+        if (!Platform.isOSX()) {
+            throw new RuntimeException("Can only add privileges on OSX.");
+        }
 
-        System.out.println("Adding 'sudo -E' to the command.");
+        System.out.println("Adding 'sudo -E -n' to the command.");
         List<String> outStringList = new ArrayList<String>();
         outStringList.add("sudo");
-        outStringList.add("-E");
+        outStringList.add("-E"); // Preserve existing environment variables.
+        outStringList.add("-n"); // non-interactive. Don't prompt for password. Must be cached or not required.
         outStringList.addAll(cmdStringList);
         return outStringList;
     }
 
+    /**
+     * Adds privileges (sudo) to the command already setup for the ProcessBuilder.
+     */
+    public static void addPrivilegesIfNeeded(ProcessBuilder pb) {
+        if (!Platform.isOSX()) {
+            return;
+        }
+
+        if (needsPrivileges()) {
+            List<String> cmdStringList = pb.command();
+            cmdStringList = addPrivileges(cmdStringList);
+            pb.command(cmdStringList);
+        }
+    }
+
+    /**
+     * On Linux, first check the SELinux boolean "deny_ptrace" and return false
+     * as we expect to be denied if that is "1".  Then expect permission to attach
+     * if we are root, so return true.  Then return false for an expected denial
+     * if "ptrace_scope" is 1, and true otherwise.
+     */
+    private static boolean canPtraceAttachLinux() throws IOException {
+        // SELinux deny_ptrace:
+        File deny_ptrace = new File("/sys/fs/selinux/booleans/deny_ptrace");
+        if (deny_ptrace.exists()) {
+            try (RandomAccessFile file = AccessController.doPrivileged(
+                    (PrivilegedExceptionAction<RandomAccessFile>) () -> new RandomAccessFile(deny_ptrace, "r"))) {
+                if (file.readByte() != '0') {
+                    return false;
+                }
+            } catch (PrivilegedActionException e) {
+                IOException t = (IOException) e.getException();
+                throw t;
+            }
+        }
+
+        // YAMA enhanced security ptrace_scope:
+        // 0 - a process can PTRACE_ATTACH to any other process running under the same uid
+        // 1 - restricted ptrace: a process must be a children of the inferior or user is root
+        // 2 - only processes with CAP_SYS_PTRACE may use ptrace or user is root
+        // 3 - no attach: no processes may use ptrace with PTRACE_ATTACH
+        File ptrace_scope = new File("/proc/sys/kernel/yama/ptrace_scope");
+        if (ptrace_scope.exists()) {
+            try (RandomAccessFile file = AccessController.doPrivileged(
+                    (PrivilegedExceptionAction<RandomAccessFile>) () -> new RandomAccessFile(ptrace_scope, "r"))) {
+                byte yama_scope = file.readByte();
+                if (yama_scope == '3') {
+                    return false;
+                }
+
+                if (!Platform.isRoot() && yama_scope != '0') {
+                    return false;
+                }
+            } catch (PrivilegedActionException e) {
+                IOException t = (IOException) e.getException();
+                throw t;
+            }
+        }
+        // Otherwise expect to be permitted:
+        return true;
+    }
+
     public static void unzipCores(File dir) {
         File[] gzCores = dir.listFiles((directory, name) -> name.matches("core(\\.\\d+)?\\.gz"));
         for (File gzCore : gzCores) {