8199871: Deprecate pack200 and unpack200 tools
authorhenryjen
Fri, 15 Jun 2018 17:34:01 -0700
changeset 50603 95c0644a1c47
parent 50602 ed8de3d0cd28
child 50604 929621cf06b4
8199871: Deprecate pack200 and unpack200 tools Reviewed-by: mchung, psandoz, abuckley
src/java.base/share/classes/com/sun/java/util/jar/pack/BandStructure.java
src/java.base/share/classes/com/sun/java/util/jar/pack/Driver.java
src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource.java
src/java.base/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java
src/java.base/share/classes/com/sun/java/util/jar/pack/PackerImpl.java
src/java.base/share/classes/com/sun/java/util/jar/pack/PropMap.java
src/java.base/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java
src/java.base/share/classes/java/util/jar/Pack200.java
src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java
src/jdk.jartool/share/classes/sun/tools/jar/Main.java
src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties
src/jdk.pack/share/classes/module-info.java
src/jdk.pack/share/native/common-unpack/defines.h
src/jdk.pack/share/native/unpack200/main.cpp
test/jdk/tools/jar/DeprecateOptionN.java
test/jdk/tools/pack200/DeprecatePack200.java
test/jdk/tools/pack200/Utils.java
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/BandStructure.java	Sat Jun 16 10:10:54 2018 +0100
+++ b/src/java.base/share/classes/com/sun/java/util/jar/pack/BandStructure.java	Fri Jun 15 17:34:01 2018 -0700
@@ -54,6 +54,7 @@
  * Define the structure and ordering of "bands" in a packed file.
  * @author John Rose
  */
+@SuppressWarnings({"removal"})
 abstract
 class BandStructure {
     static final int MAX_EFFORT = 9;
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/Driver.java	Sat Jun 16 10:10:54 2018 +0100
+++ b/src/java.base/share/classes/com/sun/java/util/jar/pack/Driver.java	Fri Jun 15 17:34:01 2018 -0700
@@ -56,9 +56,12 @@
 
 /** Command line interface for Pack200.
  */
+
+@SuppressWarnings({"removal"})
 class Driver {
-        private static final ResourceBundle RESOURCE =
-                ResourceBundle.getBundle("com.sun.java.util.jar.pack.DriverResource");
+    private static final ResourceBundle RESOURCE =
+        ResourceBundle.getBundle("com.sun.java.util.jar.pack.DriverResource");
+    private static boolean suppressDeprecateMsg = false;
 
     public static void main(String[] ava) throws IOException {
         List<String> av = new ArrayList<>(Arrays.asList(ava));
@@ -67,6 +70,7 @@
         boolean doUnpack = false;
         boolean doRepack = false;
         boolean doZip = true;
+        suppressDeprecateMsg = av.remove("-XDsuppress-tool-removal-message");
         String logFile = null;
         String verboseProp = Utils.DEBUG_VERBOSE;
 
@@ -85,6 +89,10 @@
             }
         }
 
+        if (!suppressDeprecateMsg) {
+            printDeprecateWarning(doPack, System.out);
+        }
+
         // Collect engine properties here:
         Map<String,String> engProps = new HashMap<>();
         engProps.put(verboseProp, System.getProperty(verboseProp));
@@ -395,6 +403,12 @@
     }
 
     private static
+    void printDeprecateWarning(boolean doPack, PrintStream out) {
+        String prog = doPack ? "pack200" : "unpack200";
+        out.println(MessageFormat.format(RESOURCE.getString(DriverResource.DEPRECATED), prog));
+    }
+
+    private static
     void printUsage(boolean doPack, boolean full, PrintStream out) {
         String prog = doPack ? "pack200" : "unpack200";
         String[] packUsage = (String[])RESOURCE.getObject(DriverResource.PACK_HELP);
@@ -407,6 +421,11 @@
                 break;
             }
         }
+        // Print a warning at the end
+        // The full help page is long, the beginning warning could be out of sight
+        if (full && !suppressDeprecateMsg) {
+            printDeprecateWarning(doPack, out);
+        }
     }
 
     private static
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource.java	Sat Jun 16 10:10:54 2018 +0100
+++ b/src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource.java	Fri Jun 15 17:34:01 2018 -0700
@@ -42,6 +42,7 @@
     public static final String MORE_INFO = "MORE_INFO";
     public static final String DUPLICATE_OPTION = "DUPLICATE_OPTION";
     public static final String BAD_SPEC = "BAD_SPEC";
+    public static final String DEPRECATED = "DEPRECATED";
 
     /*
      * The following are the output of 'pack200' and 'unpack200' commands.
@@ -126,6 +127,7 @@
         {MORE_INFO, "(For more information, run {0} --help .)"}, // parameter 0:command name
         {DUPLICATE_OPTION, "duplicate option: {0}"}, // parameter 0:option
         {BAD_SPEC, "bad spec for {0}: {1}"}, // parameter 0:option;parameter 1:specifier
+        {DEPRECATED, "\nWarning: The {0} tool is deprecated, and is planned for removal in a future JDK release.\n"} // parameter 0:command name
     };
 
     protected Object[][] getContents() {
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java	Sat Jun 16 10:10:54 2018 +0100
+++ b/src/java.base/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java	Fri Jun 15 17:34:01 2018 -0700
@@ -39,6 +39,7 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
 
+@SuppressWarnings({"removal"})
 class NativeUnpack {
     // Pointer to the native unpacker obj
     private long unpackerPtr;
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/PackerImpl.java	Sat Jun 16 10:10:54 2018 +0100
+++ b/src/java.base/share/classes/com/sun/java/util/jar/pack/PackerImpl.java	Fri Jun 15 17:34:01 2018 -0700
@@ -55,7 +55,7 @@
  * @author Kumar Srinivasan
  */
 
-
+@SuppressWarnings({"removal"})
 public class PackerImpl  extends TLGlobals implements Pack200.Packer {
 
     /**
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/PropMap.java	Sat Jun 16 10:10:54 2018 +0100
+++ b/src/java.base/share/classes/com/sun/java/util/jar/pack/PropMap.java	Fri Jun 15 17:34:01 2018 -0700
@@ -47,6 +47,7 @@
  * Control block for publishing Pack200 options to the other classes.
  */
 
+@SuppressWarnings({"removal"})
 final class PropMap implements SortedMap<String, String>  {
     private final TreeMap<String, String> theMap = new TreeMap<>();;
 
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java	Sat Jun 16 10:10:54 2018 +0100
+++ b/src/java.base/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java	Fri Jun 15 17:34:01 2018 -0700
@@ -53,6 +53,7 @@
  */
 
 
+@SuppressWarnings({"removal"})
 public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker {
 
     public UnpackerImpl() {}
--- a/src/java.base/share/classes/java/util/jar/Pack200.java	Sat Jun 16 10:10:54 2018 +0100
+++ b/src/java.base/share/classes/java/util/jar/Pack200.java	Fri Jun 15 17:34:01 2018 -0700
@@ -101,7 +101,10 @@
  * @author John Rose
  * @author Kumar Srinivasan
  * @since 1.5
+ * @deprecated This class is deprecated, and is planned for removal in a future
+ *             release.
  */
+@Deprecated(since="11", forRemoval=true)
 public abstract class Pack200 {
     private Pack200() {} //prevent instantiation
 
@@ -225,7 +228,10 @@
      * to be thrown.
      *
      * @since 1.5
+     * @deprecated This interface is deprecated, and is planned for removal in a
+     *             future release.
      */
+    @Deprecated(since="11", forRemoval=true)
     public interface Packer {
         /**
          * This property is a numeral giving the estimated target size N
@@ -584,7 +590,10 @@
      * <p>
      * This version of the unpacker is compatible with all previous versions.
      * @since 1.5
+     * @deprecated This interface is deprecated, and is planned for removal in a
+     *             future release.
      */
+    @Deprecated(since="11", forRemoval=true)
     public interface Unpacker {
 
         /** The string "keep", a possible value for certain properties.
--- a/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java	Sat Jun 16 10:10:54 2018 +0100
+++ b/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java	Fri Jun 15 17:34:01 2018 -0700
@@ -26,15 +26,12 @@
 package sun.tools.jar;
 
 import java.io.File;
-import java.io.PrintStream;
 import java.io.PrintWriter;
-import java.lang.module.ModuleFinder;
 import java.lang.module.ModuleDescriptor.Version;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
-
 import jdk.internal.module.ModulePath;
 import jdk.internal.module.ModuleResolution;
 
@@ -292,6 +289,10 @@
                 break;
 
             String name = args[count];
+            if (name.equals("-XDsuppress-tool-removal-message")) {
+                jartool.suppressDeprecateMsg = true;
+                continue;
+            }
             Option option = getOption(name);
             String param = null;
             if (option.hasArg) {
--- a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java	Sat Jun 16 10:10:54 2018 +0100
+++ b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java	Fri Jun 15 17:34:01 2018 -0700
@@ -31,33 +31,34 @@
 import java.lang.module.InvalidModuleDescriptorException;
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Opens;
 import java.lang.module.ModuleDescriptor.Provides;
-import java.lang.module.ModuleDescriptor.Opens;
-import java.lang.module.ModuleDescriptor.Requires;
 import java.lang.module.ModuleDescriptor.Version;
 import java.lang.module.ModuleFinder;
 import java.lang.module.ModuleReader;
 import java.lang.module.ModuleReference;
-import java.lang.module.ResolutionException;
 import java.lang.module.ResolvedModule;
 import java.net.URI;
 import java.nio.ByteBuffer;
+import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
+import java.text.MessageFormat;
 import java.util.*;
 import java.util.function.Consumer;
-import java.util.function.Supplier;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-import java.util.zip.*;
-import java.util.jar.*;
-import java.util.jar.Pack200.*;
-import java.util.jar.Manifest;
-import java.text.MessageFormat;
-
+import java.util.zip.CRC32;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
 import jdk.internal.module.Checks;
 import jdk.internal.module.ModuleHashes;
 import jdk.internal.module.ModuleHashesBuilder;
@@ -67,10 +68,10 @@
 import jdk.internal.module.ModuleTarget;
 import jdk.internal.util.jar.JarIndex;
 
-import static jdk.internal.util.jar.JarIndex.INDEX_NAME;
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
 import static java.util.jar.JarFile.MANIFEST_NAME;
 import static java.util.stream.Collectors.joining;
-import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+import static jdk.internal.util.jar.JarIndex.INDEX_NAME;
 
 /**
  * This class implements a simple utility for creating files in the JAR
@@ -151,6 +152,8 @@
      */
     boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag, pflag, dflag;
 
+    boolean suppressDeprecateMsg = false;
+
     /* To support additional GNU Style informational options */
     Consumer<PrintWriter> info;
 
@@ -238,6 +241,7 @@
     /**
      * Starts main program with the specified arguments.
      */
+    @SuppressWarnings({"removal"})
     public synchronized boolean run(String args[]) {
         ok = true;
         if (!parseArgs(args)) {
@@ -315,11 +319,14 @@
                     create(new BufferedOutputStream(out, 4096), manifest);
                 }
                 if (nflag) {
+                    if (!suppressDeprecateMsg) {
+                        warn(formatMsg("warn.flag.is.deprecated", "-n"));
+                    }
                     File packFile = createTemporaryFile(tmpbase, ".pack");
                     try {
-                        Packer packer = Pack200.newPacker();
+                        java.util.jar.Pack200.Packer packer = java.util.jar.Pack200.newPacker();
                         Map<String, String> p = packer.properties();
-                        p.put(Packer.EFFORT, "1"); // Minimal effort to conserve CPU
+                        p.put(java.util.jar.Pack200.Packer.EFFORT, "1"); // Minimal effort to conserve CPU
                         try (JarFile jarFile = new JarFile(tmpFile.getCanonicalPath());
                              OutputStream pack = new FileOutputStream(packFile))
                         {
@@ -332,7 +339,7 @@
                         try (OutputStream out = new FileOutputStream(tmpFile);
                              JarOutputStream jos = new JarOutputStream(out))
                         {
-                            Unpacker unpacker = Pack200.newUnpacker();
+                            java.util.jar.Pack200.Unpacker unpacker = java.util.jar.Pack200.newUnpacker();
                             unpacker.unpack(packFile, jos);
                         }
                     } finally {
--- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties	Sat Jun 16 10:10:54 2018 +0100
+++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties	Fri Jun 15 17:34:01 2018 -0700
@@ -131,6 +131,8 @@
         in incompatible public interfaces
 warn.release.unexpected.versioned.entry=\
         unexpected versioned entry {0}
+warn.flag.is.deprecated=\
+        Warning: The {0} option is deprecated, and is planned for removal in a future JDK release\n
 out.added.manifest=\
         added manifest
 out.added.module-info=\
@@ -170,7 +172,8 @@
 \ \   -v  generate verbose output on standard output\n\
 \ \   -f  specify archive file name\n\
 \ \   -m  include manifest information from specified manifest file\n\
-\ \   -n  perform Pack200 normalization after creating a new archive\n\
+\ \   -n  perform Pack200 normalization after creating a new archive,\n\
+\ \       this option is deprecated, and is planned for removal in a future JDK release\n\
 \ \   -e  specify application entry point for stand-alone application \n\
 \ \       bundled into an executable jar file\n\
 \ \   -0  store only; use no ZIP compression\n\
@@ -250,7 +253,8 @@
 \ Operation modifiers valid only in create mode:\n
 main.help.opt.create.normalize=\
 \  -n, --normalize            Normalize information in the new jar archive\n\
-\                             after creation
+\                             after creation. This option is deprecated, and is\n\
+\                             planned for removal in a future JDK release
 main.help.opt.create.update=\
 \ Operation modifiers valid only in create and update mode:\n
 main.help.opt.create.update.main-class=\
--- a/src/jdk.pack/share/classes/module-info.java	Sat Jun 16 10:10:54 2018 +0100
+++ b/src/jdk.pack/share/classes/module-info.java	Fri Jun 15 17:34:01 2018 -0700
@@ -36,7 +36,10 @@
  * </dl>
  *
  * @moduleGraph
+ * @deprecated This module is deprecated, and is planned for removal in a
+ *             future release.
  * @since 9
  */
+@Deprecated(since="11", forRemoval=true)
 module jdk.pack {
 }
--- a/src/jdk.pack/share/native/common-unpack/defines.h	Sat Jun 16 10:10:54 2018 +0100
+++ b/src/jdk.pack/share/native/common-unpack/defines.h	Fri Jun 15 17:34:01 2018 -0700
@@ -118,6 +118,7 @@
 #define tempname        _tempname
 #define sleep           Sleep
 #define snprintf        _snprintf
+#define PATH_SEPARATOR '\\'
 #else
 typedef signed char byte;
 #ifdef _LP64
@@ -128,6 +129,7 @@
 typedef long long unsigned julong;
 #endif
 #define MKDIR(dir) mkdir(dir, 0777);
+#define PATH_SEPARATOR '/'
 #endif
 
 #ifdef OLDCC
--- a/src/jdk.pack/share/native/unpack200/main.cpp	Sat Jun 16 10:10:54 2018 +0100
+++ b/src/jdk.pack/share/native/unpack200/main.cpp	Fri Jun 15 17:34:01 2018 -0700
@@ -139,7 +139,7 @@
 }
 
 static const char* nbasename(const char* progname) {
-  const char* slash = strrchr(progname, '/');
+  const char* slash = strrchr(progname, PATH_SEPARATOR);
   if (slash != null)  progname = ++slash;
   return progname;
 }
@@ -161,6 +161,13 @@
     "Exit Status:\n" \
     "  0 if successful, >0 if an error occurred\n"
 
+#define DEPRECATE_WARNING \
+    "\nWarning: The %s tool is deprecated, and is planned for removal in a future JDK release.\n\n"
+
+#define SUPPRESS_DEPRECATE_MSG "-XDsuppress-tool-removal-message"
+
+static bool suppress_warning = false;
+
 static void usage(unpacker* u, const char* progname, bool full = false) {
   // WinMain does not set argv[0] to the progrname
   progname = (progname != null) ? nbasename(progname) : "unpack200";
@@ -182,7 +189,11 @@
     char* buf = (char*) strdup(env);
     const char* delim = "\n\t ";
     for (char* p = strtok(buf, delim); p != null; p = strtok(null, delim)) {
-      envargs.add(p);
+      if (!strcmp(p, SUPPRESS_DEPRECATE_MSG)) {
+        suppress_warning = true;
+      } else {
+        envargs.add(p);
+      }
     }
   }
   // allocate extra margin at both head and tail
@@ -194,7 +205,11 @@
   }
   for (i = 1; i < argc; i++) {
     // note: skip argv[0] (program name)
-    *argp++ = (char*) strdup(argv[i]);  // make a scratch copy
+    if (!strcmp(argv[i], SUPPRESS_DEPRECATE_MSG)) {
+      suppress_warning = true;
+    } else {
+      *argp++ = (char*) strdup(argv[i]);  // make a scratch copy
+    }
   }
   *argp = null; // sentinel
   envargc = envargs.length();  // report this count to next_arg
@@ -293,6 +308,10 @@
   int verbose = 0;
   char* logfile = null;
 
+  if (!suppress_warning) {
+      fprintf(u.errstrm, DEPRECATE_WARNING, nbasename(argv[0]));
+  }
+
   for (;;) {
     const char* arg = (*argp == null)? "": u.saveStr(*argp);
     bool isenvarg = (argp < arg0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/tools/jar/DeprecateOptionN.java	Fri Jun 15 17:34:01 2018 -0700
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 8199871
+ * @modules jdk.jartool
+ * @summary jar -n should print out deprecation warning
+ * @run testng DeprecateOptionN
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.spi.ToolProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+public class DeprecateOptionN {
+    private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
+            .orElseThrow(() ->
+                    new RuntimeException("jar tool not found")
+            );
+
+    protected static String jar(String... options) {
+        StringWriter writer = new StringWriter();
+        PrintWriter pw = new PrintWriter(writer);
+
+        JAR_TOOL.run(pw, pw, options);
+        String output = writer.toString();
+        System.err.println(output);
+        return output;
+    }
+
+    @Test
+    public void helpCompatWithWarning() {
+        String output = jar("--help:compat");
+        assertTrue(output.contains("this option is deprecated, and is planned for removal in a future JDK release"));
+    }
+
+    @Test
+    public void helpExtraWithWarning() {
+        String output = jar("--help-extra");
+        assertTrue(output.contains("This option is deprecated, and is"));
+        assertTrue(output.contains("planned for removal in a future JDK release"));
+    }
+
+    @Test
+    public void normalizeWithWarning() throws IOException {
+        File tmp = File.createTempFile("test", null);
+        String output = jar("cnf", "test.jar", tmp.getAbsolutePath());
+        tmp.delete();
+        assertTrue(output.contains("Warning: The -n option is deprecated, and is planned for removal in a future JDK release"));
+    }
+
+    @Test
+    public void NoWarningWithoutN() throws IOException {
+        File tmp = File.createTempFile("test", null);
+        String output = jar("cf", "test.jar", tmp.getAbsolutePath());
+        tmp.delete();
+        assertFalse(output.contains("Warning: The -n option is deprecated, and is planned for removal in a future JDK release"));
+    }
+
+
+    @Test
+    public void SuppressWarning() throws IOException {
+        File tmp = File.createTempFile("test", null);
+        String output = jar("-c", "-n", "-XDsuppress-tool-removal-message",
+                "-f", "test.jar", tmp.getAbsolutePath());
+        tmp.delete();
+        assertFalse(output.contains("Warning: The -n option is deprecated, and is planned for removal in a future JDK release"));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/tools/pack200/DeprecatePack200.java	Fri Jun 15 17:34:01 2018 -0700
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 8199871
+ * @summary pack200 and unpack200 should print out deprecate warning
+ * @modules jdk.pack
+ * @compile -XDignore.symbol.file Utils.java
+ * @run testng DeprecatePack200
+ */
+
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+public class DeprecatePack200 {
+    final static String PACK200_CMD = Utils.getPack200Cmd();
+    final static String UNPACK200_CMD = Utils.getUnpack200Cmd();
+    final static Predicate<String> PACK200_MSG = Pattern.compile(
+            "Warning: The pack200(\\.exe)?? tool is deprecated, and is planned for removal in a future JDK release.")
+            .asMatchPredicate();
+    final static Predicate<String> UNPACK200_MSG = Pattern.compile(
+            "Warning: The unpack200(\\.exe)?? tool is deprecated, and is planned for removal in a future JDK release.")
+            .asMatchPredicate();
+
+    @DataProvider(name="tools")
+    public static final Object[][] provide() { return cases; }
+
+    private static final Object[][] cases = {
+        { PACK200_MSG, 1, List.of(PACK200_CMD) },
+        { PACK200_MSG, 1, List.of(PACK200_CMD, "-V") },
+        { PACK200_MSG, 2, List.of(PACK200_CMD, "--help") },
+        { PACK200_MSG, 0, List.of(PACK200_CMD, "-XDsuppress-tool-removal-message") },
+        { PACK200_MSG, 0, List.of(PACK200_CMD, "--version", "-XDsuppress-tool-removal-message") },
+        { PACK200_MSG, 0, List.of(PACK200_CMD, "-h", "-XDsuppress-tool-removal-message") },
+
+        { UNPACK200_MSG, 1, List.of(UNPACK200_CMD) },
+        { UNPACK200_MSG, 1, List.of(UNPACK200_CMD, "-V") },
+        { UNPACK200_MSG, 1, List.of(UNPACK200_CMD, "--help") },
+        { UNPACK200_MSG, 0, List.of(UNPACK200_CMD, "-XDsuppress-tool-removal-message") },
+        { UNPACK200_MSG, 0, List.of(UNPACK200_CMD, "--version", "-XDsuppress-tool-removal-message") },
+        { UNPACK200_MSG, 0, List.of(UNPACK200_CMD, "-h", "-XDsuppress-tool-removal-message") }
+    };
+
+    @Test(dataProvider = "tools")
+    public void CheckWarnings(Predicate<String> msg, long count, List<String> cmd) {
+        List<String> output = Utils.runExec(cmd, null, true);
+        assertEquals(output.stream().filter(msg).count(), count);
+    }
+}
--- a/test/jdk/tools/pack200/Utils.java	Sat Jun 16 10:10:54 2018 +0100
+++ b/test/jdk/tools/pack200/Utils.java	Fri Jun 15 17:34:01 2018 -0700
@@ -497,6 +497,10 @@
     }
 
     static List<String> runExec(List<String> cmdsList, Map<String, String> penv) {
+        return runExec(cmdsList, penv, false);
+    }
+
+    static List<String> runExec(List<String> cmdsList, Map<String, String> penv, boolean ignoreReturnValue) {
         ArrayList<String> alist = new ArrayList<String>();
         ProcessBuilder pb =
                 new ProcessBuilder(cmdsList);
@@ -529,7 +533,7 @@
                 in = rd.readLine();
             }
             retval = p.waitFor();
-            if (retval != 0) {
+            if (!ignoreReturnValue && retval != 0) {
                 throw new RuntimeException("process failed with non-zero exit");
             }
         } catch (Exception ex) {