changeset 2686:62d37c19c213

Merge
author lana
date Mon, 23 Aug 2010 19:14:20 -0700
parents a18a82d2d506 732f59013e78
children 043d2736d44c
files test/tools/pack200/Pack200Simple.sh test/tools/pack200/SegmentLimit.java
diffstat 72 files changed, 11897 insertions(+), 1236 deletions(-) [+]
line wrap: on
line diff
--- a/make/common/shared/Defs-windows.gmk	Mon Aug 23 19:13:15 2010 -0700
+++ b/make/common/shared/Defs-windows.gmk	Mon Aug 23 19:14:20 2010 -0700
@@ -89,7 +89,7 @@
 $(shell $(CYGPATH_CMD) $1 2> $(DEV_NULL))
 endef
 define OptFullPath
-$(shell if [ "$1" != "" -a -d "$1" ]; then $(CYGPATH_CMD) "$1"; else echo "$1"; fi)
+$(shell if [ "$1" != "" -a -d "$1" ]; then $(CYGPATH_CMD) "$1" 2> $(DEV_NULL); else echo "$1"; fi)
 endef
 else
 # Temporary until we upgrade to MKS 8.7, MKS pwd returns mixed mode path
--- a/make/common/shared/Defs.gmk	Mon Aug 23 19:13:15 2010 -0700
+++ b/make/common/shared/Defs.gmk	Mon Aug 23 19:14:20 2010 -0700
@@ -136,15 +136,20 @@
 $(shell echo $1 | sed -e 's@[^0-9]*\([0-9][0-9]*\.[0-9][.0-9]*\).*@\1@' )
 endef
 
+# Return one part of the version numbers, watch out for non digits.
+define VersionWord # Number Version
+$(word $1,$(subst ., ,$(subst -, ,$2)))
+endef
+
 # Given a major.minor.micro version, return the major, minor, or micro number
 define MajorVersion
-$(if $(word 1, $(subst ., ,$1)),$(word 1, $(subst ., ,$1)),0)
+$(if $(call VersionWord,1,$1),$(call VersionWord,1,$1),0)
 endef
 define MinorVersion
-$(if $(word 2, $(subst ., ,$1)),$(word 2, $(subst ., ,$1)),0)
+$(if $(call VersionWord,2,$1),$(call VersionWord,2,$1),0)
 endef
 define MicroVersion
-$(if $(word 3, $(subst ., ,$1)),$(word 3, $(subst ., ,$1)),0)
+$(if $(call VersionWord,3,$1),$(call VersionWord,3,$1),0)
 endef
 
 # Macro that returns missing, same, newer, or older $1=version $2=required
--- a/make/jdk_generic_profile.sh	Mon Aug 23 19:13:15 2010 -0700
+++ b/make/jdk_generic_profile.sh	Mon Aug 23 19:14:20 2010 -0700
@@ -340,6 +340,10 @@
 export PATH
 
 # Export variables required for Zero
+if [ "${SHARK_BUILD}" = true ] ; then
+  ZERO_BUILD=true
+  export ZERO_BUILD
+fi
 if [ "${ZERO_BUILD}" = true ] ; then
   # ZERO_LIBARCH is the name of the architecture-specific
   # subdirectory under $JAVA_HOME/jre/lib
@@ -417,4 +421,55 @@
   fi
   export LIBFFI_CFLAGS
   export LIBFFI_LIBS
+
+  # LLVM_CFLAGS, LLVM_LDFLAGS and LLVM_LIBS tell the compiler how to
+  # compile and link against LLVM
+  if [ "${SHARK_BUILD}" = true ] ; then
+    if [ "${LLVM_CONFIG}" = "" ] ; then
+      LLVM_CONFIG=$(which llvm-config 2>/dev/null)
+    fi
+    if [ ! -x "${LLVM_CONFIG}" ] ; then
+      echo "ERROR: Unable to locate llvm-config"
+      exit 1
+    fi
+    llvm_components="jit engine nativecodegen"
+
+    unset LLVM_CFLAGS
+    for flag in $("${LLVM_CONFIG}" --cxxflags $llvm_components); do
+      if echo "${flag}" | grep -q '^-[ID]'; then
+        if [ "${flag}" != "-D_DEBUG" ] ; then
+          if [ "${LLVM_CFLAGS}" != "" ] ; then
+            LLVM_CFLAGS="${LLVM_CFLAGS} "
+          fi
+          LLVM_CFLAGS="${LLVM_CFLAGS}${flag}"
+        fi
+      fi
+    done
+    llvm_version=$("${LLVM_CONFIG}" --version | sed 's/\.//; s/svn.*//')
+    LLVM_CFLAGS="${LLVM_CFLAGS} -DSHARK_LLVM_VERSION=${llvm_version}"
+
+    unset LLVM_LDFLAGS
+    for flag in $("${LLVM_CONFIG}" --ldflags $llvm_components); do
+      if echo "${flag}" | grep -q '^-L'; then
+        if [ "${LLVM_LDFLAGS}" != "" ] ; then
+          LLVM_LDFLAGS="${LLVM_LDFLAGS} "
+        fi
+        LLVM_LDFLAGS="${LLVM_LDFLAGS}${flag}"
+      fi
+    done
+
+    unset LLVM_LIBS
+    for flag in $("${LLVM_CONFIG}" --libs $llvm_components); do
+      if echo "${flag}" | grep -q '^-l'; then
+        if [ "${LLVM_LIBS}" != "" ] ; then
+          LLVM_LIBS="${LLVM_LIBS} "
+        fi
+        LLVM_LIBS="${LLVM_LIBS}${flag}"
+      fi
+    done
+
+    export LLVM_CFLAGS
+    export LLVM_LDFLAGS
+    export LLVM_LIBS
+  fi
 fi
--- a/src/share/classes/com/sun/java/util/jar/pack/Attribute.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/com/sun/java/util/jar/pack/Attribute.java	Mon Aug 23 19:14:20 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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,6 @@
 
 import java.io.*;
 import java.util.*;
-import com.sun.java.util.jar.pack.Package.Class;
 import com.sun.java.util.jar.pack.ConstantPool.*;
 
 /**
@@ -96,20 +95,20 @@
         return this.def.compareTo(that.def);
     }
 
-    static private final byte[] noBytes = {};
-    static private final HashMap canonLists = new HashMap();
-    static private final HashMap attributes = new HashMap();
-    static private final HashMap standardDefs = new HashMap();
+    private static final byte[] noBytes = {};
+    private static final Map<List<Attribute>, List<Attribute>> canonLists = new HashMap<>();
+    private static final Map<Layout, Attribute> attributes = new HashMap<>();
+    private static final Map<Layout, Attribute> standardDefs = new HashMap<>();
 
     // Canonicalized lists of trivial attrs (Deprecated, etc.)
     // are used by trimToSize, in order to reduce footprint
     // of some common cases.  (Note that Code attributes are
     // always zero size.)
-    public static List getCanonList(List al) {
+    public static List getCanonList(List<Attribute> al) {
         synchronized (canonLists) {
-            List cl = (List) canonLists.get(al);
+            List<Attribute> cl = canonLists.get(al);
             if (cl == null) {
-                cl = new ArrayList(al.size());
+                cl = new ArrayList<>(al.size());
                 cl.addAll(al);
                 cl = Collections.unmodifiableList(cl);
                 canonLists.put(al, cl);
@@ -122,7 +121,7 @@
     public static Attribute find(int ctype, String name, String layout) {
         Layout key = Layout.makeKey(ctype, name, layout);
         synchronized (attributes) {
-            Attribute a = (Attribute) attributes.get(key);
+            Attribute a = attributes.get(key);
             if (a == null) {
                 a = new Layout(ctype, name, layout).canonicalInstance();
                 attributes.put(key, a);
@@ -131,24 +130,29 @@
         }
     }
 
-    public static Object keyForLookup(int ctype, String name) {
+    public static Layout keyForLookup(int ctype, String name) {
         return Layout.makeKey(ctype, name);
     }
 
     // Find canonical empty attribute with given ctype and name,
     // and with the standard layout.
-    public static Attribute lookup(Map defs, int ctype, String name) {
-        if (defs == null)  defs = standardDefs;
-        return (Attribute) defs.get(Layout.makeKey(ctype, name));
+    public static Attribute lookup(Map<Layout, Attribute> defs, int ctype,
+            String name) {
+        if (defs == null) {
+            defs = standardDefs;
+        }
+        return defs.get(Layout.makeKey(ctype, name));
     }
-    public static Attribute define(Map defs, int ctype, String name, String layout) {
+
+    public static Attribute define(Map<Layout, Attribute> defs, int ctype,
+            String name, String layout) {
         Attribute a = find(ctype, name, layout);
         defs.put(Layout.makeKey(ctype, name), a);
         return a;
     }
 
     static {
-        Map sd = standardDefs;
+        Map<Layout, Attribute> sd = standardDefs;
         define(sd, ATTR_CONTEXT_CLASS, "Signature", "RSH");
         define(sd, ATTR_CONTEXT_CLASS, "Synthetic", "");
         define(sd, ATTR_CONTEXT_CLASS, "Deprecated", "");
@@ -244,7 +248,7 @@
              +"\n    ()[] ]"
              )
         };
-        Map sd = standardDefs;
+        Map<Layout, Attribute> sd = standardDefs;
         String defaultLayout     = mdLayouts[2];
         String annotationsLayout = mdLayouts[1] + mdLayouts[2];
         String paramsLayout      = mdLayouts[0] + annotationsLayout;
@@ -275,10 +279,6 @@
         return null;
     }
 
-    public static Map getStandardDefs() {
-        return new HashMap(standardDefs);
-    }
-
     /** Base class for any attributed object (Class, Field, Method, Code).
      *  Flags are included because they are used to help transmit the
      *  presence of attributes.  That is, flags are a mix of modifier
@@ -291,7 +291,7 @@
         protected abstract Entry[] getCPMap();
 
         protected int flags;             // defined here for convenience
-        protected List attributes;
+        protected List<Attribute> attributes;
 
         public int attributeSize() {
             return (attributes == null) ? 0 : attributes.size();
@@ -301,16 +301,15 @@
             if (attributes == null) {
                 return;
             }
-            if (attributes.size() == 0) {
+            if (attributes.isEmpty()) {
                 attributes = null;
                 return;
             }
             if (attributes instanceof ArrayList) {
-                ArrayList al = (ArrayList) attributes;
+                ArrayList<Attribute> al = (ArrayList<Attribute>)attributes;
                 al.trimToSize();
                 boolean allCanon = true;
-                for (Iterator i = al.iterator(); i.hasNext(); ) {
-                    Attribute a = (Attribute) i.next();
+                for (Attribute a : al) {
                     if (!a.isCanonical()) {
                         allCanon = false;
                     }
@@ -330,9 +329,9 @@
 
         public void addAttribute(Attribute a) {
             if (attributes == null)
-                attributes = new ArrayList(3);
+                attributes = new ArrayList<>(3);
             else if (!(attributes instanceof ArrayList))
-                attributes = new ArrayList(attributes);  // unfreeze it
+                attributes = new ArrayList<>(attributes);  // unfreeze it
             attributes.add(a);
         }
 
@@ -340,32 +339,31 @@
             if (attributes == null)       return null;
             if (!attributes.contains(a))  return null;
             if (!(attributes instanceof ArrayList))
-                attributes = new ArrayList(attributes);  // unfreeze it
+                attributes = new ArrayList<>(attributes);  // unfreeze it
             attributes.remove(a);
             return a;
         }
 
         public Attribute getAttribute(int n) {
-            return (Attribute) attributes.get(n);
+            return attributes.get(n);
         }
 
-        protected void visitRefs(int mode, Collection refs) {
+        protected void visitRefs(int mode, Collection<Entry> refs) {
             if (attributes == null)  return;
-            for (Iterator i = attributes.iterator(); i.hasNext(); ) {
-                Attribute a = (Attribute) i.next();
+            for (Attribute a : attributes) {
                 a.visitRefs(this, mode, refs);
             }
         }
 
-        static final List noAttributes = Arrays.asList(new Object[0]);
+        static final List<Attribute> noAttributes = Arrays.asList(new Attribute[0]);
 
-        public List getAttributes() {
+        public List<Attribute> getAttributes() {
             if (attributes == null)
                 return noAttributes;
             return attributes;
         }
 
-        public void setAttributes(List attrList) {
+        public void setAttributes(List<Attribute> attrList) {
             if (attrList.isEmpty())
                 attributes = null;
             else
@@ -374,8 +372,7 @@
 
         public Attribute getAttribute(String attrName) {
             if (attributes == null)  return null;
-            for (Iterator i = attributes.iterator(); i.hasNext(); ) {
-                Attribute a = (Attribute) i.next();
+            for (Attribute a : attributes) {
                 if (a.name().equals(attrName))
                     return a;
             }
@@ -384,8 +381,7 @@
 
         public Attribute getAttribute(Layout attrDef) {
             if (attributes == null)  return null;
-            for (Iterator i = attributes.iterator(); i.hasNext(); ) {
-                Attribute a = (Attribute) i.next();
+            for (Attribute a : attributes) {
                 if (a.layout() == attrDef)
                     return a;
             }
@@ -457,14 +453,8 @@
         public String layout() { return layout; }
         public Attribute canonicalInstance() { return canon; }
 
-        // Cache of name reference.
-        private Entry nameRef;   // name, for use by visitRefs
         public Entry getNameRef() {
-            Entry nameRef = this.nameRef;
-            if (nameRef == null) {
-                this.nameRef = nameRef = ConstantPool.getUtf8Entry(name());
-            }
-            return nameRef;
+            return ConstantPool.getUtf8Entry(name());
         }
 
         public boolean isEmpty() { return layout == ""; }
@@ -834,14 +824,14 @@
     */
     static //private
     Layout.Element[] tokenizeLayout(Layout self, int curCble, String layout) {
-        ArrayList col = new ArrayList(layout.length());
+        ArrayList<Layout.Element> col = new ArrayList<>(layout.length());
         tokenizeLayout(self, curCble, layout, col);
         Layout.Element[] res = new Layout.Element[col.size()];
         col.toArray(res);
         return res;
     }
     static //private
-    void tokenizeLayout(Layout self, int curCble, String layout, ArrayList col) {
+    void tokenizeLayout(Layout self, int curCble, String layout, ArrayList<Layout.Element> col) {
         boolean prevBCI = false;
         for (int len = layout.length(), i = 0; i < len; ) {
             int start = i;
@@ -899,7 +889,7 @@
             case 'T': // union: 'T' any_int union_case* '(' ')' '[' body ']'
                 kind = EK_UN;
                 i = tokenizeSInt(e, layout, i);
-                ArrayList cases = new ArrayList();
+                ArrayList<Layout.Element> cases = new ArrayList<>();
                 for (;;) {
                     // Keep parsing cases until we hit the default case.
                     if (layout.charAt(i++) != '(')
@@ -1053,7 +1043,7 @@
     }
     static //private
     String[] splitBodies(String layout) {
-        ArrayList bodies = new ArrayList();
+        ArrayList<String> bodies = new ArrayList<>();
         // Parse several independent layout bodies:  "[foo][bar]...[baz]"
         for (int i = 0; i < layout.length(); i++) {
             if (layout.charAt(i++) != '[')
@@ -1132,7 +1122,9 @@
     int parseIntBefore(String layout, int dash) {
         int end = dash;
         int beg = end;
-        while (beg > 0 && isDigit(layout.charAt(beg-1)))  --beg;
+        while (beg > 0 && isDigit(layout.charAt(beg-1))) {
+            --beg;
+        }
         if (beg == end)  return Integer.parseInt("empty");
         // skip backward over a sign
         if (beg >= 1 && layout.charAt(beg-1) == '-')  --beg;
@@ -1145,7 +1137,9 @@
         int end = beg;
         int limit = layout.length();
         if (end < limit && layout.charAt(end) == '-')  ++end;
-        while (end < limit && isDigit(layout.charAt(end)))  ++end;
+        while (end < limit && isDigit(layout.charAt(end))) {
+            ++end;
+        }
         if (beg == end)  return Integer.parseInt("empty");
         return Integer.parseInt(layout.substring(beg, end));
     }
--- a/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java	Mon Aug 23 19:14:20 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, 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,6 @@
 
 package com.sun.java.util.jar.pack;
 
-import java.io.*;
 import java.util.*;
 
 /**
@@ -40,20 +39,13 @@
         return Utils.currentPropMap().getInteger(Utils.DEBUG_VERBOSE);
     }
 
-    // Uniquification tables for factory methods:
-    private static final HashMap utf8Entries       = new HashMap();
-    private static final HashMap classEntries      = new HashMap();
-    private static final HashMap literalEntries    = new HashMap();
-    private static final HashMap signatureEntries  = new HashMap();
-    private static final HashMap descriptorEntries = new HashMap();
-    private static final HashMap memberEntries     = new HashMap();
-
     /** Factory for Utf8 string constants.
      *  Used for well-known strings like "SourceFile", "<init>", etc.
      *  Also used to back up more complex constant pool entries, like Class.
      */
     public static synchronized Utf8Entry getUtf8Entry(String value) {
-        Utf8Entry e = (Utf8Entry) utf8Entries.get(value);
+        Map<String, Utf8Entry> utf8Entries  = Utils.getUtf8Entries();
+        Utf8Entry e = utf8Entries.get(value);
         if (e == null) {
             e = new Utf8Entry(value);
             utf8Entries.put(e.stringValue(), e);
@@ -62,9 +54,10 @@
     }
     /** Factory for Class constants. */
     public static synchronized ClassEntry getClassEntry(String name) {
-        ClassEntry e = (ClassEntry) classEntries.get(name);
+        Map<String, ClassEntry> classEntries = Utils.getClassEntries();
+        ClassEntry e = classEntries.get(name);
         if (e == null) {
-            e = (ClassEntry) new ClassEntry(getUtf8Entry(name));
+            e = new ClassEntry(getUtf8Entry(name));
             assert(name.equals(e.stringValue()));
             classEntries.put(e.stringValue(), e);
         }
@@ -72,7 +65,8 @@
     }
     /** Factory for literal constants (String, Integer, etc.). */
     public static synchronized LiteralEntry getLiteralEntry(Comparable value) {
-        LiteralEntry e = (LiteralEntry) literalEntries.get(value);
+        Map<Object, LiteralEntry> literalEntries = Utils.getLiteralEntries();
+        LiteralEntry e = literalEntries.get(value);
         if (e == null) {
             if (value instanceof String)
                 e = new StringEntry(getUtf8Entry((String)value));
@@ -89,7 +83,8 @@
 
     /** Factory for signature (type) constants. */
     public static synchronized SignatureEntry getSignatureEntry(String type) {
-        SignatureEntry e = (SignatureEntry) signatureEntries.get(type);
+        Map<String, SignatureEntry> signatureEntries = Utils.getSignatureEntries();
+        SignatureEntry e = signatureEntries.get(type);
         if (e == null) {
             e = new SignatureEntry(type);
             assert(e.stringValue().equals(type));
@@ -104,8 +99,9 @@
 
     /** Factory for descriptor (name-and-type) constants. */
     public static synchronized DescriptorEntry getDescriptorEntry(Utf8Entry nameRef, SignatureEntry typeRef) {
+        Map<String, DescriptorEntry> descriptorEntries = Utils.getDescriptorEntries();
         String key = DescriptorEntry.stringValueOf(nameRef, typeRef);
-        DescriptorEntry e = (DescriptorEntry) descriptorEntries.get(key);
+        DescriptorEntry e = descriptorEntries.get(key);
         if (e == null) {
             e = new DescriptorEntry(nameRef, typeRef);
             assert(e.stringValue().equals(key))
@@ -121,8 +117,9 @@
 
     /** Factory for member reference constants. */
     public static synchronized MemberEntry getMemberEntry(byte tag, ClassEntry classRef, DescriptorEntry descRef) {
+        Map<String, MemberEntry> memberEntries = Utils.getMemberEntries();
         String key = MemberEntry.stringValueOf(tag, classRef, descRef);
-        MemberEntry e = (MemberEntry) memberEntries.get(key);
+        MemberEntry e = memberEntries.get(key);
         if (e == null) {
             e = new MemberEntry(tag, classRef, descRef);
             assert(e.stringValue().equals(key))
@@ -489,8 +486,9 @@
             String[] parts = structureSignature(value);
             formRef = getUtf8Entry(parts[0]);
             classRefs = new ClassEntry[parts.length-1];
-            for (int i = 1; i < parts.length; i++)
-                classRefs[i-1] = getClassEntry(parts[i]);
+            for (int i = 1; i < parts.length; i++) {
+                classRefs[i - 1] = getClassEntry(parts[i]);
+            }
             hashCode();  // force computation of valueHash
         }
         protected int computeValueHash() {
@@ -527,8 +525,9 @@
         String stringValueOf(Utf8Entry formRef, ClassEntry[] classRefs) {
             String[] parts = new String[1+classRefs.length];
             parts[0] = formRef.stringValue();
-            for (int i = 1; i < parts.length; i++)
-                parts[i] = classRefs[i-1].stringValue();
+            for (int i = 1; i < parts.length; i++) {
+                parts[i] = classRefs[i - 1].stringValue();
+            }
             return flattenSignature(parts).intern();
         }
 
@@ -543,19 +542,23 @@
             int size = 0;
             for (int i = min; i < max; i++) {
                 switch (form.charAt(i)) {
-                case 'D':
-                case 'J':
-                    if (countDoublesTwice) size++;
-                    break;
-                case '[':
-                    // Skip rest of array info.
-                    while (form.charAt(i) == '[') ++i;
-                    break;
-                case ';':
-                    continue;
-                default:
-                    assert(0 <= JAVA_SIGNATURE_CHARS.indexOf(form.charAt(i)));
-                    break;
+                    case 'D':
+                    case 'J':
+                        if (countDoublesTwice) {
+                            size++;
+                        }
+                        break;
+                    case '[':
+                        // Skip rest of array info.
+                        while (form.charAt(i) == '[') {
+                            ++i;
+                        }
+                        break;
+                    case ';':
+                        continue;
+                    default:
+                        assert (0 <= JAVA_SIGNATURE_CHARS.indexOf(form.charAt(i)));
+                        break;
                 }
                 size++;
             }
@@ -586,8 +589,9 @@
                 s = "/" + formRef.stringValue();
             }
             int i;
-            while ((i = s.indexOf(';')) >= 0)
-                s = s.substring(0,i) + s.substring(i+1);
+            while ((i = s.indexOf(';')) >= 0) {
+                s = s.substring(0, i) + s.substring(i + 1);
+            }
             return s;
         }
     }
@@ -732,11 +736,11 @@
             clearIndex();
             this.cpMap = cpMap;
         }
-        protected Index(String debugName, Collection cpMapList) {
+        protected Index(String debugName, Collection<Entry> cpMapList) {
             this(debugName);
             setMap(cpMapList);
         }
-        protected void setMap(Collection cpMapList) {
+        protected void setMap(Collection<Entry> cpMapList) {
             cpMap = new Entry[cpMapList.size()];
             cpMapList.toArray(cpMap);
             setMap(cpMap);
@@ -756,11 +760,13 @@
         //
         // As a special hack, if flattenSigs, signatures are
         // treated as equivalent entries of cpMap.  This is wrong
-        // fron a Collection point of view, because contains()
+        // from a Collection point of view, because contains()
         // reports true for signatures, but the iterator()
         // never produces them!
         private int findIndexOf(Entry e) {
-            if (indexKey == null)  initializeIndex();
+            if (indexKey == null) {
+                initializeIndex();
+            }
             int probe = findIndexLocation(e);
             if (indexKey[probe] != e) {
                 if (flattenSigs && e.tag == CONSTANT_Signature) {
@@ -832,7 +838,9 @@
                 System.out.println("initialize Index "+debugName+" ["+size()+"]");
             int hsize0 = (int)((cpMap.length + 10) * 1.5);
             int hsize = 1;
-            while (hsize < hsize0)  hsize <<= 1;
+            while (hsize < hsize0) {
+                hsize <<= 1;
+            }
             indexKey   = new Entry[hsize];
             indexValue = new int[hsize];
             for (int i = 0; i < cpMap.length; i++) {
@@ -855,7 +863,7 @@
             return toArray(new Entry[size()]);
         }
         public Object clone() {
-            return new Index(debugName, (Entry[]) cpMap.clone());
+            return new Index(debugName, cpMap.clone());
         }
         public String toString() {
             return "Index "+debugName+" ["+size()+"]";
@@ -901,22 +909,24 @@
     public static
     Index[] partition(Index ix, int[] keys) {
         // %%% Should move this into class Index.
-        ArrayList parts = new ArrayList();
+        ArrayList<List<Entry>> parts = new ArrayList<>();
         Entry[] cpMap = ix.cpMap;
         assert(keys.length == cpMap.length);
         for (int i = 0; i < keys.length; i++) {
             int key = keys[i];
             if (key < 0)  continue;
-            while (key >= parts.size())  parts.add(null);
-            ArrayList part = (ArrayList) parts.get(key);
+            while (key >= parts.size()) {
+                parts.add(null);
+            }
+            List<Entry> part = parts.get(key);
             if (part == null) {
-                parts.set(key, part = new ArrayList());
+                parts.set(key, part = new ArrayList<>());
             }
             part.add(cpMap[i]);
         }
         Index[] indexes = new Index[parts.size()];
         for (int key = 0; key < indexes.length; key++) {
-            ArrayList part = (ArrayList) parts.get(key);
+            List<Entry> part = parts.get(key);
             if (part == null)  continue;
             indexes[key] = new Index(ix.debugName+"/part#"+key, part);
             assert(indexes[key].indexOf(part.get(0)) == 0);
@@ -1048,9 +1058,10 @@
                     whichClasses[i] = whichClass;
                 }
                 perClassIndexes = partition(allMembers, whichClasses);
-                for (int i = 0; i < perClassIndexes.length; i++)
-                    assert(perClassIndexes[i]==null
-                            || perClassIndexes[i].assertIsSorted());
+                for (int i = 0; i < perClassIndexes.length; i++) {
+                    assert (perClassIndexes[i] == null ||
+                            perClassIndexes[i].assertIsSorted());
+                }
                 indexByTagAndClass[tag] = perClassIndexes;
             }
             int whichClass = allClasses.indexOf(classRef);
@@ -1113,7 +1124,7 @@
      *  Also, discard null from cpRefs.
      */
     public static
-    void completeReferencesIn(Set cpRefs, boolean flattenSigs) {
+    void completeReferencesIn(Set<Entry> cpRefs, boolean flattenSigs) {
         cpRefs.remove(null);
         for (ListIterator work =
                  new ArrayList(cpRefs).listIterator(cpRefs.size());
--- a/src/share/classes/com/sun/java/util/jar/pack/Driver.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/com/sun/java/util/jar/pack/Driver.java	Mon Aug 23 19:14:20 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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,6 @@
 
 package com.sun.java.util.jar.pack;
 
-import java.lang.Error;
 import java.io.*;
 import java.text.MessageFormat;
 import java.util.*;
@@ -35,10 +34,11 @@
 /** Command line interface for Pack200.
  */
 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");
 
     public static void main(String[] ava) throws IOException {
-        ArrayList<String> av = new ArrayList<String>(Arrays.asList(ava));
+        ArrayList<String> av = new ArrayList<>(Arrays.asList(ava));
 
         boolean doPack   = true;
         boolean doUnpack = false;
@@ -61,7 +61,7 @@
         }
 
         // Collect engine properties here:
-        HashMap<String,String> engProps = new HashMap<String,String>();
+        HashMap<String,String> engProps = new HashMap<>();
         engProps.put(verboseProp, System.getProperty(verboseProp));
 
         String optionMap;
@@ -75,7 +75,7 @@
         }
 
         // Collect argument properties here:
-        HashMap<String,String> avProps = new HashMap<String,String>();
+        HashMap<String,String> avProps = new HashMap<>();
         try {
             for (;;) {
                 String state = parseCommandOptions(av, optionMap, avProps);
@@ -133,8 +133,9 @@
                     if (engProps.get(verboseProp) != null)
                         fileProps.list(System.out);
                     propIn.close();
-                    for (Map.Entry<Object,Object> me : fileProps.entrySet())
-                        engProps.put((String)me.getKey(), (String)me.getValue());
+                    for (Map.Entry<Object,Object> me : fileProps.entrySet()) {
+                        engProps.put((String) me.getKey(), (String) me.getValue());
+                    }
                 } else if (state == "--version") {
                         System.out.println(MessageFormat.format(RESOURCE.getString(DriverResource.VERSION), Driver.class.getName(), "1.31, 07/05/05"));
                     return;
@@ -493,7 +494,7 @@
         String resultString = null;
 
         // Convert options string into optLines dictionary.
-        TreeMap<String,String[]> optmap = new TreeMap<String,String[]>();
+        TreeMap<String,String[]> optmap = new TreeMap<>();
     loadOptmap:
         for (String optline : options.split("\n")) {
             String[] words = optline.split("\\p{Space}+");
@@ -687,7 +688,9 @@
         // Report number of arguments consumed.
         args.subList(0, argp.nextIndex()).clear();
         // Report any unconsumed partial argument.
-        while (pbp.hasPrevious())  args.add(0, pbp.previous());
+        while (pbp.hasPrevious()) {
+            args.add(0, pbp.previous());
+        }
         //System.out.println(args+" // "+properties+" -> "+resultString);
         return resultString;
     }
--- a/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java	Mon Aug 23 19:14:20 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -28,13 +28,8 @@
 
 import java.nio.*;
 import java.io.*;
-import java.nio.channels.*;
-import java.util.Date;
 import java.util.jar.*;
 import java.util.zip.*;
-import java.util.*;
-//import com.sun.java.util.jar.pack.Pack200;
-
 
 class NativeUnpack {
     // Pointer to the native unpacker obj
@@ -91,13 +86,13 @@
     NativeUnpack(UnpackerImpl p200) {
         super();
         _p200  = p200;
-        _props = p200._props;
+        _props = p200.props;
         p200._nunp = this;
     }
 
     // for JNI callbacks
     static private Object currentInstance() {
-        UnpackerImpl p200 = (UnpackerImpl) Utils.currentInstance.get();
+        UnpackerImpl p200 = (UnpackerImpl) Utils.getTLGlobals();
         return (p200 == null)? null: p200._nunp;
     }
 
@@ -216,10 +211,10 @@
                 ++_fileCount;
                 updateProgress();
             }
+            presetInput = getUnusedInput();
             long consumed = finish();
             if (_verbose > 0)
                 Utils.log.info("bytes consumed = "+consumed);
-            presetInput = getUnusedInput();
             if (presetInput == null &&
                 !Utils.isPackMagic(Utils.readMagic(in))) {
                 break;
--- a/src/share/classes/com/sun/java/util/jar/pack/Package.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/com/sun/java/util/jar/pack/Package.java	Mon Aug 23 19:14:20 2010 -0700
@@ -25,9 +25,9 @@
 
 package com.sun.java.util.jar.pack;
 
+import com.sun.java.util.jar.pack.Attribute.Layout;
 import java.lang.reflect.Modifier;
 import java.util.*;
-import java.util.zip.*;
 import java.util.jar.*;
 import java.io.*;
 import com.sun.java.util.jar.pack.ConstantPool.*;
@@ -77,10 +77,11 @@
         cp = new ConstantPool.IndexGroup();
         classes.clear();
         files.clear();
+        BandStructure.nextSeqForDebug = 0;
     }
 
     int getPackageVersion() {
-        return (package_majver << 16) + (int)package_minver;
+        return (package_majver << 16) + package_minver;
     }
 
     // Special empty versions of Code and InnerClasses, used for markers.
@@ -89,7 +90,7 @@
     public static final Attribute.Layout attrSourceFileSpecial;
     public static final Map attrDefs;
     static {
-        HashMap ad = new HashMap(2);
+        HashMap<Layout, Attribute> ad = new HashMap<>(3);
         attrCodeEmpty = Attribute.define(ad, ATTR_CONTEXT_METHOD,
                                          "Code", "").layout();
         attrInnerClassesEmpty = Attribute.define(ad, ATTR_CONTEXT_CLASS,
@@ -159,9 +160,9 @@
         }
     }
 
-    ArrayList classes = new ArrayList();
+    ArrayList<Package.Class> classes = new ArrayList<>();
 
-    public List getClasses() {
+    public List<Package.Class> getClasses() {
         return classes;
     }
 
@@ -186,11 +187,11 @@
         ClassEntry[] interfaces;
 
         // Class parts
-        ArrayList fields;
-        ArrayList methods;
+        ArrayList<Field> fields;
+        ArrayList<Method> methods;
         //ArrayList attributes;  // in Attribute.Holder.this.attributes
         // Note that InnerClasses may be collected at the package level.
-        ArrayList innerClasses;
+        ArrayList<InnerClass> innerClasses;
 
         Class(int flags, ClassEntry thisClass, ClassEntry superClass, ClassEntry[] interfaces) {
             this.magic      = JAVA_MAGIC;
@@ -270,7 +271,7 @@
             if (a != olda) {
                 if (verbose > 2)
                     Utils.log.fine("recoding obvious SourceFile="+obvious);
-                List newAttrs = new ArrayList(getAttributes());
+                List<Attribute> newAttrs = new ArrayList<>(getAttributes());
                 int where = newAttrs.indexOf(olda);
                 newAttrs.set(where, a);
                 setAttributes(newAttrs);
@@ -295,12 +296,12 @@
         boolean hasInnerClasses() {
             return innerClasses != null;
         }
-        List getInnerClasses() {
+        List<InnerClass> getInnerClasses() {
             return innerClasses;
         }
 
-        public void setInnerClasses(Collection ics) {
-            innerClasses = (ics == null) ? null : new ArrayList(ics);
+        public void setInnerClasses(Collection<InnerClass> ics) {
+            innerClasses = (ics == null) ? null : new ArrayList<InnerClass>(ics);
             // Edit the attribute list, if necessary.
             Attribute a = getAttribute(attrInnerClassesEmpty);
             if (innerClasses != null && a == null)
@@ -318,19 +319,18 @@
          *  The order of the resulting list is consistent
          *  with that of Package.this.allInnerClasses.
          */
-        public List computeGloballyImpliedICs() {
-            HashSet cpRefs = new HashSet();
+        public List<InnerClass> computeGloballyImpliedICs() {
+            HashSet<Entry> cpRefs = new HashSet<>();
             {   // This block temporarily displaces this.innerClasses.
-                ArrayList innerClassesSaved = innerClasses;
+                ArrayList<InnerClass> innerClassesSaved = innerClasses;
                 innerClasses = null;  // ignore for the moment
                 visitRefs(VRM_CLASSIC, cpRefs);
                 innerClasses = innerClassesSaved;
             }
             ConstantPool.completeReferencesIn(cpRefs, true);
 
-            HashSet icRefs = new HashSet();
-            for (Iterator i = cpRefs.iterator(); i.hasNext(); ) {
-                Entry e = (Entry) i.next();
+            HashSet<Entry> icRefs = new HashSet<>();
+            for (Entry e : cpRefs) {
                 // Restrict cpRefs to InnerClasses entries only.
                 if (!(e instanceof ClassEntry))  continue;
                 // For every IC reference, add its outers also.
@@ -345,9 +345,8 @@
             // This loop is structured this way so as to accumulate
             // entries into impliedICs in an order which reflects
             // the order of allInnerClasses.
-            ArrayList impliedICs = new ArrayList();
-            for (Iterator i = allInnerClasses.iterator(); i.hasNext(); ) {
-                InnerClass ic = (InnerClass) i.next();
+            ArrayList<InnerClass> impliedICs = new ArrayList<>();
+            for (InnerClass ic : allInnerClasses) {
                 // This one is locally relevant if it describes
                 // a member of the current class, or if the current
                 // class uses it somehow.  In the particular case
@@ -366,10 +365,11 @@
 
         // Helper for both minimizing and expanding.
         // Computes a symmetric difference.
-        private List computeICdiff() {
-            List impliedICs = computeGloballyImpliedICs();
-            List actualICs  = getInnerClasses();
-            if (actualICs == null)  actualICs = Collections.EMPTY_LIST;
+        private List<InnerClass> computeICdiff() {
+            List<InnerClass> impliedICs = computeGloballyImpliedICs();
+            List<InnerClass> actualICs  = getInnerClasses();
+            if (actualICs == null)
+                actualICs = Collections.EMPTY_LIST;
 
             // Symmetric difference is calculated from I, A like this:
             //  diff = (I+A) - (I*A)
@@ -388,8 +388,8 @@
                 // Diff is A since I is empty.
             }
             // (I*A) is non-trivial
-            HashSet center = new HashSet(actualICs);
-            center.retainAll(new HashSet(impliedICs));
+            HashSet<InnerClass> center = new HashSet<>(actualICs);
+            center.retainAll(new HashSet<>(impliedICs));
             impliedICs.addAll(actualICs);
             impliedICs.removeAll(center);
             // Diff is now I^A = (I+A)-(I*A).
@@ -407,9 +407,9 @@
          *  to use the globally implied ICs changed.
          */
         void minimizeLocalICs() {
-            List diff = computeICdiff();
-            List actualICs = innerClasses;
-            List localICs;  // will be the diff, modulo edge cases
+            List<InnerClass> diff = computeICdiff();
+            List<InnerClass> actualICs = innerClasses;
+            List<InnerClass> localICs;  // will be the diff, modulo edge cases
             if (diff.isEmpty()) {
                 // No diff, so transmit no attribute.
                 localICs = null;
@@ -439,12 +439,12 @@
          *  Otherwise, return positive if any IC tuples were added.
          */
         int expandLocalICs() {
-            List localICs = innerClasses;
-            List actualICs;
+            List<InnerClass> localICs = innerClasses;
+            List<InnerClass> actualICs;
             int changed;
             if (localICs == null) {
                 // Diff was empty.  (Common case.)
-                List impliedICs = computeGloballyImpliedICs();
+                List<InnerClass> impliedICs = computeGloballyImpliedICs();
                 if (impliedICs.isEmpty()) {
                     actualICs = null;
                     changed = 0;
@@ -490,7 +490,7 @@
             protected Entry[] getCPMap() {
                 return cpMap;
             }
-            protected void visitRefs(int mode, Collection refs) {
+            protected void visitRefs(int mode, Collection<Entry> refs) {
                 if (verbose > 2)  Utils.log.fine("visitRefs "+this);
                 // Careful:  The descriptor is used by the package,
                 // but the classfile breaks it into component refs.
@@ -518,7 +518,7 @@
                 super(flags, descriptor);
                 assert(!descriptor.isMethod());
                 if (fields == null)
-                    fields = new ArrayList();
+                    fields = new ArrayList<>();
                 boolean added = fields.add(this);
                 assert(added);
                 order = fields.size();
@@ -543,7 +543,7 @@
                 super(flags, descriptor);
                 assert(descriptor.isMethod());
                 if (methods == null)
-                    methods = new ArrayList();
+                    methods = new ArrayList<>();
                 boolean added = methods.add(this);
                 assert(added);
             }
@@ -573,7 +573,7 @@
                     code.strip(attrName);
                 super.strip(attrName);
             }
-            protected void visitRefs(int mode, Collection refs) {
+            protected void visitRefs(int mode, Collection<Entry> refs) {
                 super.visitRefs(mode, refs);
                 if (code != null) {
                     if (mode == VRM_CLASSIC) {
@@ -614,7 +614,7 @@
             super.strip(attrName);
         }
 
-        protected void visitRefs(int mode, Collection refs) {
+        protected void visitRefs(int mode, Collection<Entry> refs) {
             if (verbose > 2)  Utils.log.fine("visitRefs "+this);
             refs.add(thisClass);
             refs.add(superClass);
@@ -641,7 +641,7 @@
             super.visitRefs(mode, refs);
         }
 
-        protected void visitInnerClassRefs(int mode, Collection refs) {
+        protected void visitInnerClassRefs(int mode, Collection<Entry> refs) {
             Package.visitInnerClassRefs(innerClasses, mode, refs);
         }
 
@@ -713,16 +713,15 @@
     }
 
     // What non-class files are in this unit?
-    ArrayList files = new ArrayList();
+    ArrayList<File> files = new ArrayList<>();
 
-    public List getFiles() {
+    public List<File> getFiles() {
         return files;
     }
 
-    public List getClassStubs() {
-        ArrayList classStubs = new ArrayList(classes.size());
-        for (Iterator i = classes.iterator(); i.hasNext(); ) {
-            Class cls = (Class) i.next();
+    public List<File> getClassStubs() {
+        ArrayList<File> classStubs = new ArrayList<>(classes.size());
+        for (Class cls : classes) {
             assert(cls.file.isClassStub());
             classStubs.add(cls.file);
         }
@@ -840,7 +839,7 @@
         public InputStream getInputStream() {
             InputStream in = new ByteArrayInputStream(append.toByteArray());
             if (prepend.size() == 0)  return in;
-            ArrayList isa = new ArrayList(prepend.size()+1);
+            ArrayList<InputStream> isa = new ArrayList<>(prepend.size()+1);
             for (Iterator i = prepend.iterator(); i.hasNext(); ) {
                 byte[] bytes = (byte[]) i.next();
                 isa.add(new ByteArrayInputStream(bytes));
@@ -849,7 +848,7 @@
             return new SequenceInputStream(Collections.enumeration(isa));
         }
 
-        protected void visitRefs(int mode, Collection refs) {
+        protected void visitRefs(int mode, Collection<Entry> refs) {
             assert(name != null);
             refs.add(name);
         }
@@ -877,8 +876,8 @@
     }
 
     // Is there a globally declared table of inner classes?
-    ArrayList allInnerClasses = new ArrayList();
-    HashMap   allInnerClassesByThis;
+    ArrayList<InnerClass> allInnerClasses = new ArrayList<>();
+    HashMap<ClassEntry, InnerClass>   allInnerClassesByThis;
 
     public
     List getAllInnerClasses() {
@@ -886,15 +885,14 @@
     }
 
     public
-    void setAllInnerClasses(Collection ics) {
+    void setAllInnerClasses(Collection<InnerClass> ics) {
         assert(ics != allInnerClasses);
         allInnerClasses.clear();
         allInnerClasses.addAll(ics);
 
         // Make an index:
-        allInnerClassesByThis = new HashMap(allInnerClasses.size());
-        for (Iterator i = allInnerClasses.iterator(); i.hasNext(); ) {
-            InnerClass ic = (InnerClass) i.next();
+        allInnerClassesByThis = new HashMap<>(allInnerClasses.size());
+        for (InnerClass ic : allInnerClasses) {
             Object pic = allInnerClassesByThis.put(ic.thisClass, ic);
             assert(pic == null);  // caller must ensure key uniqueness!
         }
@@ -904,7 +902,7 @@
     public
     InnerClass getGlobalInnerClass(Entry thisClass) {
         assert(thisClass instanceof ClassEntry);
-        return (InnerClass) allInnerClassesByThis.get(thisClass);
+        return allInnerClassesByThis.get(thisClass);
     }
 
     static
@@ -963,7 +961,7 @@
             return this.thisClass.compareTo(that.thisClass);
         }
 
-        protected void visitRefs(int mode, Collection refs) {
+        protected void visitRefs(int mode, Collection<Entry> refs) {
             refs.add(thisClass);
             if (mode == VRM_CLASSIC || !predictable) {
                 // If the name can be demangled, the package omits
@@ -980,7 +978,7 @@
 
     // Helper for building InnerClasses attributes.
     static private
-    void visitInnerClassRefs(Collection innerClasses, int mode, Collection refs) {
+    void visitInnerClassRefs(Collection innerClasses, int mode, Collection<Entry> refs) {
         if (innerClasses == null) {
             return;  // no attribute; nothing to do
         }
@@ -1165,9 +1163,8 @@
         }
     }
 
-    protected void visitRefs(int mode, Collection refs) {
-        for (Iterator i = classes.iterator(); i.hasNext(); ) {
-            Class c = (Class)i.next();
+    protected void visitRefs(int mode, Collection<Entry> refs) {
+        for ( Class c : classes) {
             c.visitRefs(mode, refs);
         }
         if (mode != VRM_CLASSIC) {
@@ -1259,7 +1256,7 @@
     }
 
     // Use this before writing the package file.
-    void buildGlobalConstantPool(Set requiredEntries) {
+    void buildGlobalConstantPool(Set<Entry> requiredEntries) {
         if (verbose > 1)
             Utils.log.fine("Checking for unused CP entries");
         requiredEntries.add(getRefString(""));  // uconditionally present
@@ -1291,9 +1288,8 @@
 
     // Use this before writing the class files.
     void ensureAllClassFiles() {
-        HashSet fileSet = new HashSet(files);
-        for (Iterator i = classes.iterator(); i.hasNext(); ) {
-            Class cls = (Class) i.next();
+        HashSet<File> fileSet = new HashSet<>(files);
+        for (Class cls : classes) {
             // Add to the end of ths list:
             if (!fileSet.contains(cls.file))
                 files.add(cls.file);
--- a/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java	Mon Aug 23 19:14:20 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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,12 +25,11 @@
 
 package com.sun.java.util.jar.pack;
 
+import com.sun.java.util.jar.pack.Attribute.Layout;
 import java.util.*;
 import java.util.jar.*;
-import java.util.zip.*;
 import java.io.*;
 import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeEvent;
 
 
 /*
@@ -41,31 +40,22 @@
  */
 
 
-public class PackerImpl implements Pack200.Packer {
+public class PackerImpl  extends TLGlobals implements Pack200.Packer {
 
     /**
      * Constructs a Packer object and sets the initial state of
      * the packer engines.
      */
-    public PackerImpl() {
-        _props = new PropMap();
-        //_props.getProperty() consults defaultProps invisibly.
-        //_props.putAll(defaultProps);
-    }
-
-
-    // Private stuff.
-    final PropMap _props;
+    public PackerImpl() {}
 
     /**
      * Get the set of options for the pack and unpack engines.
      * @return A sorted association of option key strings to option values.
      */
-    public SortedMap properties() {
-        return _props;
+    public SortedMap<String, String> properties() {
+        return props;
     }
 
-
     //Driver routines
 
     /**
@@ -78,21 +68,22 @@
      */
     public void pack(JarFile in, OutputStream out) throws IOException {
         assert(Utils.currentInstance.get() == null);
-        TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null :
-            TimeZone.getDefault();
+        TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE))
+                      ? null
+                      : TimeZone.getDefault();
         try {
             Utils.currentInstance.set(this);
             if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
 
-            if ("0".equals(_props.getProperty(Pack200.Packer.EFFORT))) {
+            if ("0".equals(props.getProperty(Pack200.Packer.EFFORT))) {
                 Utils.copyJarFile(in, out);
             } else {
                 (new DoPack()).run(in, out);
-                in.close();
             }
         } finally {
             Utils.currentInstance.set(null);
             if (tz != null) TimeZone.setDefault(tz);
+            in.close();
         }
     }
 
@@ -112,21 +103,20 @@
      */
     public void pack(JarInputStream in, OutputStream out) throws IOException {
         assert(Utils.currentInstance.get() == null);
-        TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null :
+        TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null :
             TimeZone.getDefault();
         try {
             Utils.currentInstance.set(this);
             if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
-            if ("0".equals(_props.getProperty(Pack200.Packer.EFFORT))) {
+            if ("0".equals(props.getProperty(Pack200.Packer.EFFORT))) {
                 Utils.copyJarFile(in, out);
             } else {
                 (new DoPack()).run(in, out);
-                in.close();
             }
         } finally {
             Utils.currentInstance.set(null);
             if (tz != null) TimeZone.setDefault(tz);
-
+            in.close();
         }
     }
     /**
@@ -134,7 +124,7 @@
      * @param listener  An object to be invoked when a property is changed.
      */
     public void addPropertyChangeListener(PropertyChangeListener listener) {
-        _props.addListener(listener);
+        props.addListener(listener);
     }
 
     /**
@@ -142,7 +132,7 @@
      * @param listener  The PropertyChange listener to be removed.
      */
     public void removePropertyChangeListener(PropertyChangeListener listener) {
-        _props.removeListener(listener);
+        props.removeListener(listener);
     }
 
 
@@ -151,11 +141,11 @@
 
     // The packer worker.
     private class DoPack {
-        final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE);
+        final int verbose = props.getInteger(Utils.DEBUG_VERBOSE);
 
         {
-            _props.setInteger(Pack200.Packer.PROGRESS, 0);
-            if (verbose > 0) Utils.log.info(_props.toString());
+            props.setInteger(Pack200.Packer.PROGRESS, 0);
+            if (verbose > 0) Utils.log.info(props.toString());
         }
 
         // Here's where the bits are collected before getting packed:
@@ -163,7 +153,7 @@
 
         final String unknownAttrCommand;
         {
-            String uaMode = _props.getProperty(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS);
+            String uaMode = props.getProperty(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS);
             if (!(Pack200.Packer.STRIP.equals(uaMode) ||
                   Pack200.Packer.PASS.equals(uaMode) ||
                   Pack200.Packer.ERROR.equals(uaMode))) {
@@ -191,13 +181,12 @@
             };
             for (int i = 0; i < ctypes.length; i++) {
                 String pfx = keys[i];
-                Map map = _props.prefixMap(pfx);
-                for (Iterator j = map.keySet().iterator(); j.hasNext(); ) {
-                    String key = (String) j.next();
+                Map<String, String> map = props.prefixMap(pfx);
+                for (String key : map.keySet()) {
                     assert(key.startsWith(pfx));
                     String name = key.substring(pfx.length());
-                    String layout = _props.getProperty(key);
-                    Object lkey = Attribute.keyForLookup(ctypes[i], name);
+                    String layout = props.getProperty(key);
+                    Layout lkey = Attribute.keyForLookup(ctypes[i], name);
                     if (Pack200.Packer.STRIP.equals(layout) ||
                         Pack200.Packer.PASS.equals(layout) ||
                         Pack200.Packer.ERROR.equals(layout)) {
@@ -222,25 +211,25 @@
         }
 
         final boolean keepFileOrder
-            = _props.getBoolean(Pack200.Packer.KEEP_FILE_ORDER);
+            = props.getBoolean(Pack200.Packer.KEEP_FILE_ORDER);
         final boolean keepClassOrder
-            = _props.getBoolean(Utils.PACK_KEEP_CLASS_ORDER);
+            = props.getBoolean(Utils.PACK_KEEP_CLASS_ORDER);
 
         final boolean keepModtime
-            = Pack200.Packer.KEEP.equals(_props.getProperty(Pack200.Packer.MODIFICATION_TIME));
+            = Pack200.Packer.KEEP.equals(props.getProperty(Pack200.Packer.MODIFICATION_TIME));
         final boolean latestModtime
-            = Pack200.Packer.LATEST.equals(_props.getProperty(Pack200.Packer.MODIFICATION_TIME));
+            = Pack200.Packer.LATEST.equals(props.getProperty(Pack200.Packer.MODIFICATION_TIME));
         final boolean keepDeflateHint
-            = Pack200.Packer.KEEP.equals(_props.getProperty(Pack200.Packer.DEFLATE_HINT));
+            = Pack200.Packer.KEEP.equals(props.getProperty(Pack200.Packer.DEFLATE_HINT));
         {
             if (!keepModtime && !latestModtime) {
-                int modtime = _props.getTime(Pack200.Packer.MODIFICATION_TIME);
+                int modtime = props.getTime(Pack200.Packer.MODIFICATION_TIME);
                 if (modtime != Constants.NO_MODTIME) {
                     pkg.default_modtime = modtime;
                 }
             }
             if (!keepDeflateHint) {
-                boolean deflate_hint = _props.getBoolean(Pack200.Packer.DEFLATE_HINT);
+                boolean deflate_hint = props.getBoolean(Pack200.Packer.DEFLATE_HINT);
                 if (deflate_hint) {
                     pkg.default_options |= Constants.AO_DEFLATE_HINT;
                 }
@@ -254,10 +243,10 @@
         final long segmentLimit;
         {
             long limit;
-            if (_props.getProperty(Pack200.Packer.SEGMENT_LIMIT, "").equals(""))
+            if (props.getProperty(Pack200.Packer.SEGMENT_LIMIT, "").equals(""))
                 limit = -1;
             else
-                limit = _props.getLong(Pack200.Packer.SEGMENT_LIMIT);
+                limit = props.getLong(Pack200.Packer.SEGMENT_LIMIT);
             limit = Math.min(Integer.MAX_VALUE, limit);
             limit = Math.max(-1, limit);
             if (limit == -1)
@@ -265,10 +254,10 @@
             segmentLimit = limit;
         }
 
-        final List passFiles;  // parsed pack.pass.file options
+        final List<String> passFiles;  // parsed pack.pass.file options
         {
             // Which class files will be passed through?
-            passFiles = _props.getProperties(Pack200.Packer.PASS_FILE_PFX);
+            passFiles = props.getProperties(Pack200.Packer.PASS_FILE_PFX);
             for (ListIterator i = passFiles.listIterator(); i.hasNext(); ) {
                 String file = (String) i.next();
                 if (file == null) { i.remove(); continue; }
@@ -283,28 +272,28 @@
         {
             // Fill in permitted range of major/minor version numbers.
             int ver;
-            if ((ver = _props.getInteger(Utils.COM_PREFIX+"min.class.majver")) != 0)
+            if ((ver = props.getInteger(Utils.COM_PREFIX+"min.class.majver")) != 0)
                 pkg.min_class_majver = (short) ver;
-            if ((ver = _props.getInteger(Utils.COM_PREFIX+"min.class.minver")) != 0)
+            if ((ver = props.getInteger(Utils.COM_PREFIX+"min.class.minver")) != 0)
                 pkg.min_class_minver = (short) ver;
-            if ((ver = _props.getInteger(Utils.COM_PREFIX+"max.class.majver")) != 0)
+            if ((ver = props.getInteger(Utils.COM_PREFIX+"max.class.majver")) != 0)
                 pkg.max_class_majver = (short) ver;
-            if ((ver = _props.getInteger(Utils.COM_PREFIX+"max.class.minver")) != 0)
+            if ((ver = props.getInteger(Utils.COM_PREFIX+"max.class.minver")) != 0)
                 pkg.max_class_minver = (short) ver;
-            if ((ver = _props.getInteger(Utils.COM_PREFIX+"package.minver")) != 0)
+            if ((ver = props.getInteger(Utils.COM_PREFIX+"package.minver")) != 0)
                 pkg.package_minver = (short) ver;
-            if ((ver = _props.getInteger(Utils.COM_PREFIX+"package.majver")) != 0)
+            if ((ver = props.getInteger(Utils.COM_PREFIX+"package.majver")) != 0)
                 pkg.package_majver = (short) ver;
         }
 
         {
             // Hook for testing:  Forces use of special archive modes.
-            int opt = _props.getInteger(Utils.COM_PREFIX+"archive.options");
+            int opt = props.getInteger(Utils.COM_PREFIX+"archive.options");
             if (opt != 0)
                 pkg.default_options |= opt;
         }
 
-        // (Done collecting options from _props.)
+        // (Done collecting options from props.)
 
         boolean isClassFile(String name) {
             if (!name.endsWith(".class"))  return false;
@@ -423,16 +412,18 @@
                 Package.File file = null;
                 // (5078608) : discount the resource files in META-INF
                 // from segment computation.
-                long inflen = (isMetaInfFile(name)) ?  0L :
-                                inFile.getInputLength();
+                long inflen = (isMetaInfFile(name))
+                              ? 0L
+                              : inFile.getInputLength();
 
                 if ((segmentSize += inflen) > segmentLimit) {
                     segmentSize -= inflen;
                     int nextCount = -1;  // don't know; it's a stream
                     flushPartial(out, nextCount);
                 }
-                if (verbose > 1)
+                if (verbose > 1) {
                     Utils.log.fine("Reading " + name);
+                }
 
                 assert(je.isDirectory() == name.endsWith("/"));
 
@@ -450,18 +441,18 @@
         }
 
         void run(JarFile in, OutputStream out) throws IOException {
-            List inFiles = scanJar(in);
+            List<InFile> inFiles = scanJar(in);
 
             if (verbose > 0)
                 Utils.log.info("Reading " + inFiles.size() + " files...");
 
             int numDone = 0;
-            for (Iterator i = inFiles.iterator(); i.hasNext(); ) {
-                InFile inFile = (InFile) i.next();
+            for (InFile inFile : inFiles) {
                 String name      = inFile.name;
                 // (5078608) : discount the resource files completely from segmenting
-                long inflen = (isMetaInfFile(name)) ? 0L :
-                                inFile.getInputLength() ;
+                long inflen = (isMetaInfFile(name))
+                               ? 0L
+                               : inFile.getInputLength() ;
                 if ((segmentSize += inflen) > segmentLimit) {
                     segmentSize -= inflen;
                     // Estimate number of remaining segments:
@@ -530,11 +521,11 @@
         }
 
         void flushPartial(OutputStream out, int nextCount) throws IOException {
-            if (pkg.files.size() == 0 && pkg.classes.size() == 0) {
+            if (pkg.files.isEmpty() && pkg.classes.isEmpty()) {
                 return;  // do not flush an empty segment
             }
             flushPackage(out, Math.max(1, nextCount));
-            _props.setInteger(Pack200.Packer.PROGRESS, 25);
+            props.setInteger(Pack200.Packer.PROGRESS, 25);
             // In case there will be another segment:
             makeNextPackage();
             segmentCount += 1;
@@ -543,10 +534,10 @@
         }
 
         void flushAll(OutputStream out) throws IOException {
-            _props.setInteger(Pack200.Packer.PROGRESS, 50);
+            props.setInteger(Pack200.Packer.PROGRESS, 50);
             flushPackage(out, 0);
             out.flush();
-            _props.setInteger(Pack200.Packer.PROGRESS, 100);
+            props.setInteger(Pack200.Packer.PROGRESS, 100);
             segmentCount += 1;
             segmentTotalSize += segmentSize;
             segmentSize = 0;
@@ -582,11 +573,11 @@
             pkg.trimStubs();
 
             // Do some stripping, maybe.
-            if (_props.getBoolean(Utils.COM_PREFIX+"strip.debug"))        pkg.stripAttributeKind("Debug");
-            if (_props.getBoolean(Utils.COM_PREFIX+"strip.compile"))      pkg.stripAttributeKind("Compile");
-            if (_props.getBoolean(Utils.COM_PREFIX+"strip.constants"))    pkg.stripAttributeKind("Constant");
-            if (_props.getBoolean(Utils.COM_PREFIX+"strip.exceptions"))   pkg.stripAttributeKind("Exceptions");
-            if (_props.getBoolean(Utils.COM_PREFIX+"strip.innerclasses")) pkg.stripAttributeKind("InnerClasses");
+            if (props.getBoolean(Utils.COM_PREFIX+"strip.debug"))        pkg.stripAttributeKind("Debug");
+            if (props.getBoolean(Utils.COM_PREFIX+"strip.compile"))      pkg.stripAttributeKind("Compile");
+            if (props.getBoolean(Utils.COM_PREFIX+"strip.constants"))    pkg.stripAttributeKind("Constant");
+            if (props.getBoolean(Utils.COM_PREFIX+"strip.exceptions"))   pkg.stripAttributeKind("Exceptions");
+            if (props.getBoolean(Utils.COM_PREFIX+"strip.innerclasses")) pkg.stripAttributeKind("InnerClasses");
 
             // Must choose an archive version; PackageWriter does not.
             if (pkg.package_majver <= 0)  pkg.choosePackageVersion();
@@ -606,11 +597,10 @@
             }
         }
 
-        List scanJar(JarFile jf) throws IOException {
+        List<InFile> scanJar(JarFile jf) throws IOException {
             // Collect jar entries, preserving order.
-            List inFiles = new ArrayList();
-            for (Enumeration e = jf.entries(); e.hasMoreElements(); ) {
-                JarEntry je = (JarEntry) e.nextElement();
+            List<InFile> inFiles = new ArrayList<>();
+            for (JarEntry je : Collections.list(jf.entries())) {
                 InFile inFile = new InFile(jf, je);
                 assert(je.isDirectory() == inFile.name.endsWith("/"));
                 inFiles.add(inFile);
--- a/src/share/classes/com/sun/java/util/jar/pack/PropMap.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/com/sun/java/util/jar/pack/PropMap.java	Mon Aug 23 19:14:20 2010 -0700
@@ -91,7 +91,7 @@
                   String.valueOf(Boolean.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)));
 
         // The segment size is unlimited
-        props.put(Pack200.Packer.SEGMENT_LIMIT, "");
+        props.put(Pack200.Packer.SEGMENT_LIMIT, "-1");
 
         // Preserve file ordering by default.
         props.put(Pack200.Packer.KEEP_FILE_ORDER, Pack200.Packer.TRUE);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/java/util/jar/pack/TLGlobals.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.java.util.jar.pack;
+
+import com.sun.java.util.jar.pack.ConstantPool.ClassEntry;
+import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry;
+import com.sun.java.util.jar.pack.ConstantPool.LiteralEntry;
+import com.sun.java.util.jar.pack.ConstantPool.MemberEntry;
+import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry;
+import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedMap;
+
+/*
+ * @author ksrini
+ */
+
+/*
+ * This class provides a container to hold the global variables, for packer
+ * and unpacker instances. This is typically stashed away in a ThreadLocal,
+ * and the storage is destroyed upon completion. Therefore any local
+ * references to these members must be eliminated appropriately to prevent a
+ * memory leak.
+ */
+class TLGlobals {
+    // Global environment
+    final PropMap props;
+
+    // Needed by ConstantPool.java
+    private final Map<String, Utf8Entry> utf8Entries;
+    private final Map<String, ClassEntry> classEntries;
+    private final Map<Object, LiteralEntry> literalEntries;
+    private final Map<String, SignatureEntry> signatureEntries;
+    private final Map<String, DescriptorEntry> descriptorEntries;
+    private final Map<String, MemberEntry> memberEntries;
+
+    TLGlobals() {
+        utf8Entries = new HashMap<>();
+        classEntries = new HashMap<>();
+        literalEntries = new HashMap<>();
+        signatureEntries = new HashMap<>();
+        descriptorEntries = new HashMap<>();
+        memberEntries = new HashMap<>();
+        props = new PropMap();
+    }
+
+    SortedMap<Object, Object> getPropMap() {
+        return props;
+    }
+
+    Map<String, Utf8Entry> getUtf8Entries() {
+        return utf8Entries;
+    }
+
+    Map<String, ClassEntry> getClassEntries() {
+        return classEntries;
+    }
+
+    Map<Object, LiteralEntry> getLiteralEntries() {
+        return literalEntries;
+    }
+
+    Map<String, DescriptorEntry> getDescriptorEntries() {
+         return descriptorEntries;
+    }
+
+    Map<String, SignatureEntry> getSignatureEntries() {
+        return signatureEntries;
+    }
+
+    Map<String, MemberEntry> getMemberEntries() {
+        return memberEntries;
+    }
+}
--- a/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java	Mon Aug 23 19:14:20 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -30,7 +30,6 @@
 import java.util.zip.*;
 import java.io.*;
 import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeEvent;
 
 /*
  * Implementation of the Pack provider.
@@ -40,7 +39,7 @@
  */
 
 
-public class UnpackerImpl implements Pack200.Unpacker {
+public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker {
 
 
     /**
@@ -48,7 +47,7 @@
      * @param listener  An object to be invoked when a property is changed.
      */
     public void addPropertyChangeListener(PropertyChangeListener listener) {
-        _props.addListener(listener);
+        props.addListener(listener);
     }
 
 
@@ -57,25 +56,19 @@
      * @param listener  The PropertyChange listener to be removed.
      */
     public void removePropertyChangeListener(PropertyChangeListener listener) {
-        _props.removeListener(listener);
+        props.removeListener(listener);
     }
 
-    public UnpackerImpl() {
-        _props = new PropMap();
-        //_props.getProperty() consults defaultProps invisibly.
-        //_props.putAll(defaultProps);
-    }
+    public UnpackerImpl() {}
 
-    // Private stuff.
-    final PropMap _props;
 
 
     /**
      * Get the set of options for the pack and unpack engines.
      * @return A sorted association of option key strings to option values.
      */
-    public SortedMap properties() {
-        return _props;
+    public SortedMap<String, String> properties() {
+        return props;
     }
 
     // Back-pointer to NativeUnpacker, when active.
@@ -101,19 +94,20 @@
      */
     public void unpack(InputStream in0, JarOutputStream out) throws IOException {
         assert(Utils.currentInstance.get() == null);
-        TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null :
-            TimeZone.getDefault();
+        TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE))
+                      ? null
+                      : TimeZone.getDefault();
 
         try {
             Utils.currentInstance.set(this);
             if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
-            final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE);
+            final int verbose = props.getInteger(Utils.DEBUG_VERBOSE);
             BufferedInputStream in = new BufferedInputStream(in0);
             if (Utils.isJarMagic(Utils.readMagic(in))) {
                 if (verbose > 0)
                     Utils.log.info("Copying unpacked JAR file...");
                 Utils.copyJarFile(new JarInputStream(in), out);
-            } else if (_props.getBoolean(Utils.DEBUG_DISABLE_NATIVE)) {
+            } else if (props.getBoolean(Utils.DEBUG_DISABLE_NATIVE)) {
                 (new DoUnpack()).run(in, out);
                 in.close();
                 Utils.markJarFile(out);
@@ -142,36 +136,38 @@
         // %%% Reconsider if native unpacker learns to memory-map the file.
         FileInputStream instr = new FileInputStream(in);
         unpack(instr, out);
-        if (_props.getBoolean(Utils.UNPACK_REMOVE_PACKFILE)) {
+        if (props.getBoolean(Utils.UNPACK_REMOVE_PACKFILE)) {
             in.delete();
         }
     }
 
     private class DoUnpack {
-        final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE);
+        final int verbose = props.getInteger(Utils.DEBUG_VERBOSE);
 
         {
-            _props.setInteger(Pack200.Unpacker.PROGRESS, 0);
+            props.setInteger(Pack200.Unpacker.PROGRESS, 0);
         }
 
         // Here's where the bits are read from disk:
         final Package pkg = new Package();
 
         final boolean keepModtime
-            = Pack200.Packer.KEEP.equals(_props.getProperty(Utils.UNPACK_MODIFICATION_TIME, Pack200.Packer.KEEP));
+            = Pack200.Packer.KEEP.equals(
+              props.getProperty(Utils.UNPACK_MODIFICATION_TIME, Pack200.Packer.KEEP));
         final boolean keepDeflateHint
-            = Pack200.Packer.KEEP.equals(_props.getProperty(Pack200.Unpacker.DEFLATE_HINT, Pack200.Packer.KEEP));
+            = Pack200.Packer.KEEP.equals(
+              props.getProperty(Pack200.Unpacker.DEFLATE_HINT, Pack200.Packer.KEEP));
         final int modtime;
         final boolean deflateHint;
         {
             if (!keepModtime) {
-                modtime = _props.getTime(Utils.UNPACK_MODIFICATION_TIME);
+                modtime = props.getTime(Utils.UNPACK_MODIFICATION_TIME);
             } else {
                 modtime = pkg.default_modtime;
             }
 
             deflateHint = (keepDeflateHint) ? false :
-                _props.getBoolean(java.util.jar.Pack200.Unpacker.DEFLATE_HINT);
+                props.getBoolean(java.util.jar.Pack200.Unpacker.DEFLATE_HINT);
         }
 
         // Checksum apparatus.
@@ -181,7 +177,7 @@
 
         public void run(BufferedInputStream in, JarOutputStream out) throws IOException {
             if (verbose > 0) {
-                _props.list(System.out);
+                props.list(System.out);
             }
             for (int seg = 1; ; seg++) {
                 unpackSegment(in, out);
@@ -194,25 +190,26 @@
         }
 
         private void unpackSegment(InputStream in, JarOutputStream out) throws IOException {
-            _props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"0");
+            props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"0");
             // Process the output directory or jar output.
             new PackageReader(pkg, in).read();
 
-            if (_props.getBoolean("unpack.strip.debug"))    pkg.stripAttributeKind("Debug");
-            if (_props.getBoolean("unpack.strip.compile"))  pkg.stripAttributeKind("Compile");
-            _props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"50");
+            if (props.getBoolean("unpack.strip.debug"))    pkg.stripAttributeKind("Debug");
+            if (props.getBoolean("unpack.strip.compile"))  pkg.stripAttributeKind("Compile");
+            props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"50");
             pkg.ensureAllClassFiles();
             // Now write out the files.
-            HashSet classesToWrite = new HashSet(pkg.getClasses());
+            HashSet<Package.Class> classesToWrite = new HashSet<>(pkg.getClasses());
             for (Iterator i = pkg.getFiles().iterator(); i.hasNext(); ) {
                 Package.File file = (Package.File) i.next();
                 String name = file.nameString;
                 JarEntry je = new JarEntry(Utils.getJarEntryName(name));
                 boolean deflate;
 
-                deflate = (keepDeflateHint) ? (((file.options & Constants.FO_DEFLATE_HINT) != 0) ||
-                                                   ((pkg.default_options & Constants.AO_DEFLATE_HINT) != 0)) :
-                    deflateHint;
+                deflate = (keepDeflateHint)
+                          ? (((file.options & Constants.FO_DEFLATE_HINT) != 0) ||
+                            ((pkg.default_options & Constants.AO_DEFLATE_HINT) != 0))
+                          : deflateHint;
 
                 boolean needCRC = !deflate;  // STORE mode requires CRC
 
@@ -250,7 +247,7 @@
                     Utils.log.info("Writing "+Utils.zeString((ZipEntry)je));
             }
             assert(classesToWrite.isEmpty());
-            _props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"100");
+            props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"100");
             pkg.reset();  // reset for the next segment, if any
         }
     }
--- a/src/share/classes/com/sun/java/util/jar/pack/Utils.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/com/sun/java/util/jar/pack/Utils.java	Mon Aug 23 19:14:20 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,13 @@
 
 package com.sun.java.util.jar.pack;
 
+import com.sun.java.util.jar.pack.Attribute.Layout;
+import com.sun.java.util.jar.pack.ConstantPool.ClassEntry;
+import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry;
+import com.sun.java.util.jar.pack.ConstantPool.LiteralEntry;
+import com.sun.java.util.jar.pack.ConstantPool.MemberEntry;
+import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry;
+import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry;
 import java.util.*;
 import java.util.jar.*;
 import java.util.zip.*;
@@ -113,17 +120,46 @@
      */
     static final String PACK_ZIP_ARCHIVE_MARKER_COMMENT = "PACK200";
 
-   // Keep a TLS point to the current Packer or Unpacker.
-   // This makes it simpler to supply environmental options
+    // Keep a TLS point to the global data and environment.
+    // This makes it simpler to supply environmental options
     // to the engine code, especially the native code.
-    static final ThreadLocal currentInstance = new ThreadLocal();
+    static final ThreadLocal<TLGlobals> currentInstance = new ThreadLocal<>();
+
+    // convenience methods to access the TL globals
+    static TLGlobals getTLGlobals() {
+        return currentInstance.get();
+    }
+
+    static Map<String, Utf8Entry> getUtf8Entries() {
+        return getTLGlobals().getUtf8Entries();
+    }
+
+    static Map<String, ClassEntry> getClassEntries() {
+        return getTLGlobals().getClassEntries();
+    }
+
+    static Map<Object, LiteralEntry> getLiteralEntries() {
+        return getTLGlobals().getLiteralEntries();
+    }
+
+    static Map<String, DescriptorEntry> getDescriptorEntries() {
+         return getTLGlobals().getDescriptorEntries();
+    }
+
+    static Map<String, SignatureEntry> getSignatureEntries() {
+        return getTLGlobals().getSignatureEntries();
+    }
+
+    static Map<String, MemberEntry> getMemberEntries() {
+        return getTLGlobals().getMemberEntries();
+    }
 
     static PropMap currentPropMap() {
         Object obj = currentInstance.get();
         if (obj instanceof PackerImpl)
-            return ((PackerImpl)obj)._props;
+            return ((PackerImpl)obj).props;
         if (obj instanceof UnpackerImpl)
-            return ((UnpackerImpl)obj)._props;
+            return ((UnpackerImpl)obj).props;
         return null;
     }
 
--- a/src/share/classes/com/sun/jndi/ldap/Connection.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/com/sun/jndi/ldap/Connection.java	Mon Aug 23 19:14:20 2010 -0700
@@ -813,7 +813,8 @@
         try {
             while (true) {
                 try {
-                    inbuf = new byte[10];
+                    // type and length (at most 128 octets for long form)
+                    inbuf = new byte[129];
 
                     offset = 0;
                     seqlen = 0;
--- a/src/share/classes/java/lang/AbstractStringBuilder.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/java/lang/AbstractStringBuilder.java	Mon Aug 23 19:14:20 2010 -0700
@@ -470,7 +470,7 @@
     public AbstractStringBuilder append(CharSequence s, int start, int end) {
         if (s == null)
             s = "null";
-        if ((start < 0) || (end < 0) || (start > end) || (end > s.length()))
+        if ((start < 0) || (start > end) || (end > s.length()))
             throw new IndexOutOfBoundsException(
                 "start " + start + ", end " + end + ", s.length() "
                 + s.length());
@@ -529,7 +529,8 @@
      *         or {@code offset+len > str.length}
      */
     public AbstractStringBuilder append(char str[], int offset, int len) {
-        ensureCapacityInternal(count + len);
+        if (len > 0)                // let arraycopy report AIOOBE for len < 0
+            ensureCapacityInternal(count + len);
         System.arraycopy(str, offset, value, count, len);
         count += len;
         return this;
--- a/src/share/classes/java/lang/Thread.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/java/lang/Thread.java	Mon Aug 23 19:14:20 2010 -0700
@@ -414,6 +414,18 @@
     }
 
     /**
+     * Throws CloneNotSupportedException as a Thread can not be meaningfully
+     * cloned. Construct a new Thread instead.
+     *
+     * @throws  CloneNotSupportedException
+     *          always
+     */
+    @Override
+    protected Object clone() throws CloneNotSupportedException {
+        throw new CloneNotSupportedException();
+    }
+
+    /**
      * Allocates a new {@code Thread} object. This constructor has the same
      * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
      * {@code (null, null, gname)}, where {@code gname} is a newly generated
--- a/src/share/classes/java/lang/Throwable.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/java/lang/Throwable.java	Mon Aug 23 19:14:20 2010 -0700
@@ -200,7 +200,16 @@
      * @serial
      * @since 1.7
      */
-    private List<Throwable> suppressedExceptions = Collections.emptyList();
+    private List<Throwable> suppressedExceptions = null;
+    /*
+     * This field is lazily initialized when the first suppressed
+     * exception is added.
+     *
+     * OutOfMemoryError is preallocated in the VM for better OOM
+     * diagnosability during VM initialization. Constructor can't
+     * be not invoked. If a new field to be added in the future must
+     * be initialized to non-null, it requires a synchronized VM change.
+     */
 
     /** Message for trying to suppress a null exception. */
     private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception.";
@@ -329,7 +338,7 @@
      *          cause is nonexistent or unknown.
      * @since 1.4
      */
-    public Throwable getCause() {
+    public synchronized Throwable getCause() {
         return (cause==this ? null : cause);
     }
 
@@ -563,7 +572,7 @@
                 s.println("\tat " + traceElement);
 
             // Print suppressed exceptions, if any
-            for (Throwable se : suppressedExceptions)
+            for (Throwable se : getSuppressedExceptions())
                 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
 
             // Print cause, if any
@@ -604,7 +613,7 @@
                 s.println(prefix + "\t... " + framesInCommon + " more");
 
             // Print suppressed exceptions, if any
-            for (Throwable se : suppressedExceptions)
+            for (Throwable se : getSuppressedExceptions())
                 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
                                            prefix +"\t", dejaVu);
 
@@ -747,7 +756,9 @@
             if (defensiveCopy[i] == null)
                 throw new NullPointerException("stackTrace[" + i + "]");
 
-        this.stackTrace = defensiveCopy;
+        synchronized (this) {
+            this.stackTrace = defensiveCopy;
+        }
     }
 
     /**
@@ -772,11 +783,11 @@
     private void readObject(ObjectInputStream s)
         throws IOException, ClassNotFoundException {
         s.defaultReadObject();     // read in all fields
-        List<Throwable> suppressed = Collections.emptyList();
+        List<Throwable> suppressed = null;
         if (suppressedExceptions != null &&
             !suppressedExceptions.isEmpty()) { // Copy Throwables to new list
             suppressed = new ArrayList<Throwable>();
-            for(Throwable t : suppressedExceptions) {
+            for (Throwable t : suppressedExceptions) {
                 if (t == null)
                     throw new NullPointerException(NULL_CAUSE_MESSAGE);
                 suppressed.add(t);
@@ -819,7 +830,7 @@
         if (exception == this)
             throw new IllegalArgumentException("Self-suppression not permitted");
 
-        if (suppressedExceptions.size() == 0)
+        if (suppressedExceptions == null)
             suppressedExceptions = new ArrayList<Throwable>();
         suppressedExceptions.add(exception);
     }
@@ -835,7 +846,10 @@
      *         suppressed to deliver this exception.
      * @since 1.7
      */
-    public Throwable[] getSuppressedExceptions() {
-        return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
+    public synchronized Throwable[] getSuppressedExceptions() {
+        if (suppressedExceptions == null)
+            return EMPTY_THROWABLE_ARRAY;
+        else
+            return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
     }
 }
--- a/src/share/classes/java/net/HttpCookie.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/java/net/HttpCookie.java	Mon Aug 23 19:14:20 2010 -0700
@@ -1093,14 +1093,8 @@
         return sb.toString();
     }
 
-    private static SimpleDateFormat[] cDateFormats = null;
-    static {
-            cDateFormats = new SimpleDateFormat[COOKIE_DATE_FORMATS.length];
-            for (int i = 0; i < COOKIE_DATE_FORMATS.length; i++) {
-                cDateFormats[i] = new SimpleDateFormat(COOKIE_DATE_FORMATS[i], Locale.US);
-                cDateFormats[i].setTimeZone(TimeZone.getTimeZone("GMT"));
-            }
-    }
+    static final TimeZone GMT = TimeZone.getTimeZone("GMT");
+
     /*
      * @param dateString        a date string in one of the formats
      *                          defined in Netscape cookie spec
@@ -1109,12 +1103,14 @@
      *                          time and the time specified by dateString
      */
     private long expiryDate2DeltaSeconds(String dateString) {
-        for (SimpleDateFormat df : cDateFormats) {
+        for (int i = 0; i < COOKIE_DATE_FORMATS.length; i++) {
+            SimpleDateFormat df = new SimpleDateFormat(COOKIE_DATE_FORMATS[i], Locale.US);
+            df.setTimeZone(GMT);
             try {
                 Date date = df.parse(dateString);
                 return (date.getTime() - whenCreated) / 1000;
             } catch (Exception e) {
-
+                // Ignore, try the next date format
             }
         }
         return 0;
--- a/src/share/classes/java/net/URI.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/java/net/URI.java	Mon Aug 23 19:14:20 2010 -0700
@@ -856,9 +856,7 @@
         try {
             return new URI(str);
         } catch (URISyntaxException x) {
-            IllegalArgumentException y = new IllegalArgumentException();
-            y.initCause(x);
-            throw y;
+            throw new IllegalArgumentException(x.getMessage(), x);
         }
     }
 
--- a/src/share/classes/java/security/KeyStore.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/java/security/KeyStore.java	Mon Aug 23 19:14:20 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -131,17 +131,19 @@
  * to read existing entries from the keystore, or to write new entries
  * into the keystore:
  * <pre>
+ *    KeyStore.ProtectionParameter protParam =
+ *        new KeyStore.PasswordProtection(password);
+ *
  *    // get my private key
  *    KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
- *        ks.getEntry("privateKeyAlias", password);
+ *        ks.getEntry("privateKeyAlias", protParam);
  *    PrivateKey myPrivateKey = pkEntry.getPrivateKey();
  *
  *    // save my secret key
  *    javax.crypto.SecretKey mySecretKey;
  *    KeyStore.SecretKeyEntry skEntry =
  *        new KeyStore.SecretKeyEntry(mySecretKey);
- *    ks.setEntry("secretKeyAlias", skEntry,
- *        new KeyStore.PasswordProtection(password));
+ *    ks.setEntry("secretKeyAlias", skEntry, protParam);
  *
  *    // store away the keystore
  *    java.io.FileOutputStream fos = null;
--- a/src/share/classes/java/sql/Date.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/java/sql/Date.java	Mon Aug 23 19:14:20 2010 -0700
@@ -103,27 +103,46 @@
      *         JDBC date escape format (yyyy-mm-dd)
      */
     public static Date valueOf(String s) {
-        int year;
-        int month;
-        int day;
+        final int YEAR_LENGTH = 4;
+        final int MONTH_LENGTH = 2;
+        final int DAY_LENGTH = 2;
+        final int MAX_MONTH = 12;
+        final int MAX_DAY = 31;
         int firstDash;
         int secondDash;
+        Date d = null;
 
-        if (s == null) throw new java.lang.IllegalArgumentException();
-
-        firstDash = s.indexOf('-');
-        secondDash = s.indexOf('-', firstDash+1);
-        if ((firstDash > 0) & (secondDash > 0) & (secondDash < s.length()-1)) {
-            year = Integer.parseInt(s.substring(0, firstDash)) - 1900;
-            month = Integer.parseInt(s.substring(firstDash+1, secondDash)) - 1;
-            day = Integer.parseInt(s.substring(secondDash+1));
-        } else {
+        if (s == null) {
             throw new java.lang.IllegalArgumentException();
         }
 
-        return new Date(year, month, day);
+        firstDash = s.indexOf('-');
+        secondDash = s.indexOf('-', firstDash + 1);
+
+        if ((firstDash > 0) && (secondDash > 0) && (secondDash < s.length() - 1)) {
+            String yyyy = s.substring(0, firstDash);
+            String mm = s.substring(firstDash + 1, secondDash);
+            String dd = s.substring(secondDash + 1);
+            if (yyyy.length() == YEAR_LENGTH && mm.length() == MONTH_LENGTH &&
+                    dd.length() == DAY_LENGTH) {
+                int year = Integer.parseInt(yyyy);
+                int month = Integer.parseInt(mm);
+                int day = Integer.parseInt(dd);
+
+                if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) {
+                    d = new Date(year - 1900, month - 1, day);
+                }
+            }
+        }
+        if (d == null) {
+            throw new java.lang.IllegalArgumentException();
+        }
+
+        return d;
+
     }
 
+
     /**
      * Formats a date in the date escape format yyyy-mm-dd.
      * <P>
--- a/src/share/classes/sun/net/www/protocol/file/FileURLConnection.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/sun/net/www/protocol/file/FileURLConnection.java	Mon Aug 23 19:14:20 2010 -0700
@@ -59,7 +59,7 @@
     String filename;
     boolean isDirectory = false;
     boolean exists = false;
-    List files;
+    List<String> files;
 
     long length = -1;
     long lastModified = 0;
@@ -81,7 +81,10 @@
                 filename = file.toString();
                 isDirectory = file.isDirectory();
                 if (isDirectory) {
-                    files = (List) Arrays.asList(file.list());
+                    String[] fileList = file.list();
+                    if (fileList == null)
+                        throw new FileNotFoundException(filename + " exists, but is not accessible");
+                    files = Arrays.<String>asList(fileList);
                 } else {
 
                     is = new BufferedInputStream(new FileInputStream(filename));
@@ -197,7 +200,7 @@
                 Collections.sort(files, Collator.getInstance());
 
                 for (int i = 0 ; i < files.size() ; i++) {
-                    String fileName = (String)files.get(i);
+                    String fileName = files.get(i);
                     buf.append(fileName);
                     buf.append("\n");
                 }
--- a/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Mon Aug 23 19:14:20 2010 -0700
@@ -1768,6 +1768,10 @@
         // Not really necessary for a tunnel, but can't hurt
         requests.setIfNotSet("Accept", acceptString);
 
+        if (http.getHttpKeepAliveSet()) {
+            requests.setIfNotSet("Proxy-Connection", "keep-alive");
+        }
+
         setPreemptiveProxyAuthentication(requests);
 
          /* Log the CONNECT request */
--- a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Mon Aug 23 19:14:20 2010 -0700
@@ -536,9 +536,11 @@
         }
     }
 
-    private long read0(ByteBuffer[] bufs) throws IOException {
-        if (bufs == null)
-            throw new NullPointerException();
+    public long read(ByteBuffer[] dsts, int offset, int length)
+        throws IOException
+    {
+        if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
+            throw new IndexOutOfBoundsException();
         synchronized (readLock) {
             synchronized (stateLock) {
                 ensureOpen();
@@ -552,7 +554,7 @@
                     return 0;
                 readerThread = NativeThread.current();
                 do {
-                    n = IOUtil.read(fd, bufs, nd);
+                    n = IOUtil.read(fd, dsts, offset, length, nd);
                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
                 return IOStatus.normalize(n);
             } finally {
@@ -563,15 +565,6 @@
         }
     }
 
-    public long read(ByteBuffer[] dsts, int offset, int length)
-        throws IOException
-    {
-        if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
-           throw new IndexOutOfBoundsException();
-        // ## Fix IOUtil.write so that we can avoid this array copy
-        return read0(Util.subsequence(dsts, offset, length));
-    }
-
     public int write(ByteBuffer buf) throws IOException {
         if (buf == null)
             throw new NullPointerException();
@@ -599,9 +592,11 @@
         }
     }
 
-    private long write0(ByteBuffer[] bufs) throws IOException {
-        if (bufs == null)
-            throw new NullPointerException();
+    public long write(ByteBuffer[] srcs, int offset, int length)
+        throws IOException
+    {
+        if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
+            throw new IndexOutOfBoundsException();
         synchronized (writeLock) {
             synchronized (stateLock) {
                 ensureOpen();
@@ -615,7 +610,7 @@
                     return 0;
                 writerThread = NativeThread.current();
                 do {
-                    n = IOUtil.write(fd, bufs, nd);
+                    n = IOUtil.write(fd, srcs, offset, length, nd);
                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
                 return IOStatus.normalize(n);
             } finally {
@@ -626,15 +621,6 @@
         }
     }
 
-    public long write(ByteBuffer[] srcs, int offset, int length)
-        throws IOException
-    {
-        if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
-            throw new IndexOutOfBoundsException();
-        // ## Fix IOUtil.write so that we can avoid this array copy
-        return write0(Util.subsequence(srcs, offset, length));
-    }
-
     protected void implConfigureBlocking(boolean block) throws IOException {
         IOUtil.configureBlocking(fd, block);
     }
--- a/src/share/classes/sun/nio/ch/FileChannelImpl.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/sun/nio/ch/FileChannelImpl.java	Mon Aug 23 19:14:20 2010 -0700
@@ -143,7 +143,11 @@
         }
     }
 
-    private long read0(ByteBuffer[] dsts) throws IOException {
+    public long read(ByteBuffer[] dsts, int offset, int length)
+        throws IOException
+    {
+        if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
+            throw new IndexOutOfBoundsException();
         ensureOpen();
         if (!readable)
             throw new NonReadableChannelException();
@@ -156,7 +160,7 @@
                 if (!isOpen())
                     return 0;
                 do {
-                    n = IOUtil.read(fd, dsts, nd);
+                    n = IOUtil.read(fd, dsts, offset, length, nd);
                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
                 return IOStatus.normalize(n);
             } finally {
@@ -167,15 +171,6 @@
         }
     }
 
-    public long read(ByteBuffer[] dsts, int offset, int length)
-        throws IOException
-    {
-        if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
-           throw new IndexOutOfBoundsException();
-        // ## Fix IOUtil.write so that we can avoid this array copy
-        return read0(Util.subsequence(dsts, offset, length));
-    }
-
     public int write(ByteBuffer src) throws IOException {
         ensureOpen();
         if (!writable)
@@ -200,7 +195,11 @@
         }
     }
 
-    private long write0(ByteBuffer[] srcs) throws IOException {
+    public long write(ByteBuffer[] srcs, int offset, int length)
+        throws IOException
+    {
+        if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
+            throw new IndexOutOfBoundsException();
         ensureOpen();
         if (!writable)
             throw new NonWritableChannelException();
@@ -213,7 +212,7 @@
                 if (!isOpen())
                     return 0;
                 do {
-                    n = IOUtil.write(fd, srcs, nd);
+                    n = IOUtil.write(fd, srcs, offset, length, nd);
                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
                 return IOStatus.normalize(n);
             } finally {
@@ -224,16 +223,6 @@
         }
     }
 
-    public long write(ByteBuffer[] srcs, int offset, int length)
-        throws IOException
-    {
-        if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
-           throw new IndexOutOfBoundsException();
-        // ## Fix IOUtil.write so that we can avoid this array copy
-        return write0(Util.subsequence(srcs, offset, length));
-    }
-
-
     // -- Other operations --
 
     public long position() throws IOException {
@@ -440,24 +429,45 @@
         }
     }
 
-    private long transferToTrustedChannel(long position, int icount,
+    // Maximum size to map when using a mapped buffer
+    private static final long MAPPED_TRANSFER_SIZE = 8L*1024L*1024L;
+
+    private long transferToTrustedChannel(long position, long count,
                                           WritableByteChannel target)
         throws IOException
     {
-        if (  !((target instanceof FileChannelImpl)
-                || (target instanceof SelChImpl)))
+        boolean isSelChImpl = (target instanceof SelChImpl);
+        if (!((target instanceof FileChannelImpl) || isSelChImpl))
             return IOStatus.UNSUPPORTED;
 
         // Trusted target: Use a mapped buffer
-        MappedByteBuffer dbb = null;
-        try {
-            dbb = map(MapMode.READ_ONLY, position, icount);
-            // ## Bug: Closing this channel will not terminate the write
-            return target.write(dbb);
-        } finally {
-            if (dbb != null)
-                unmap(dbb);
+        long remaining = count;
+        while (remaining > 0L) {
+            long size = Math.min(remaining, MAPPED_TRANSFER_SIZE);
+            try {
+                MappedByteBuffer dbb = map(MapMode.READ_ONLY, position, size);
+                try {
+                    // ## Bug: Closing this channel will not terminate the write
+                    int n = target.write(dbb);
+                    assert n >= 0;
+                    remaining -= n;
+                    if (isSelChImpl) {
+                        // one attempt to write to selectable channel
+                        break;
+                    }
+                    assert n > 0;
+                    position += n;
+                } finally {
+                    unmap(dbb);
+                }
+            } catch (IOException ioe) {
+                // Only throw exception if no bytes have been written
+                if (remaining == count)
+                    throw ioe;
+                break;
+            }
         }
+        return count - remaining;
     }
 
     private long transferToArbitraryChannel(long position, int icount,
@@ -535,20 +545,34 @@
                                          long position, long count)
         throws IOException
     {
-        // Note we could loop here to accumulate more at once
         synchronized (src.positionLock) {
-            long p = src.position();
-            int icount = (int)Math.min(Math.min(count, Integer.MAX_VALUE),
-                                       src.size() - p);
-            // ## Bug: Closing this channel will not terminate the write
-            MappedByteBuffer bb = src.map(MapMode.READ_ONLY, p, icount);
-            try {
-                long n = write(bb, position);
-                src.position(p + n);
-                return n;
-            } finally {
-                unmap(bb);
+            long pos = src.position();
+            long max = Math.min(count, src.size() - pos);
+
+            long remaining = max;
+            long p = pos;
+            while (remaining > 0L) {
+                long size = Math.min(remaining, MAPPED_TRANSFER_SIZE);
+                // ## Bug: Closing this channel will not terminate the write
+                MappedByteBuffer bb = src.map(MapMode.READ_ONLY, p, size);
+                try {
+                    long n = write(bb, position);
+                    assert n > 0;
+                    p += n;
+                    position += n;
+                    remaining -= n;
+                } catch (IOException ioe) {
+                    // Only throw exception if no bytes have been written
+                    if (remaining == max)
+                        throw ioe;
+                    break;
+                } finally {
+                    unmap(bb);
+                }
             }
+            long nwritten = max - remaining;
+            src.position(pos + nwritten);
+            return nwritten;
         }
     }
 
--- a/src/share/classes/sun/nio/ch/IOUtil.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/sun/nio/ch/IOUtil.java	Mon Aug 23 19:14:20 2010 -0700
@@ -38,34 +38,6 @@
 
     private IOUtil() { }                // No instantiation
 
-    /*
-     * Returns the index of first buffer in bufs with remaining,
-     * or -1 if there is nothing left
-     */
-    private static int remaining(ByteBuffer[] bufs) {
-        int numBufs = bufs.length;
-        for (int i=0; i<numBufs; i++) {
-            if (bufs[i].hasRemaining()) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    /*
-     * Returns a new ByteBuffer array with only unfinished buffers in it
-     */
-    private static ByteBuffer[] skipBufs(ByteBuffer[] bufs,
-                                         int nextWithRemaining)
-    {
-        int newSize = bufs.length - nextWithRemaining;
-        ByteBuffer[] temp = new ByteBuffer[newSize];
-        for (int i=0; i<newSize; i++) {
-            temp[i] = bufs[i + nextWithRemaining];
-        }
-        return temp;
-    }
-
     static int write(FileDescriptor fd, ByteBuffer src, long position,
                      NativeDispatcher nd, Object lock)
         throws IOException
@@ -93,7 +65,7 @@
             }
             return n;
         } finally {
-            Util.releaseTemporaryDirectBuffer(bb);
+            Util.offerFirstTemporaryDirectBuffer(bb);
         }
     }
 
@@ -125,88 +97,81 @@
     static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
         throws IOException
     {
-        int nextWithRemaining = remaining(bufs);
-        // if all bufs are empty we should return immediately
-        if (nextWithRemaining < 0)
-            return 0;
-        // If some bufs are empty we should skip them
-        if (nextWithRemaining > 0)
-            bufs = skipBufs(bufs, nextWithRemaining);
+        return write(fd, bufs, 0, bufs.length, nd);
+    }
 
-        int numBufs = bufs.length;
+    static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
+                      NativeDispatcher nd)
+        throws IOException
+    {
+        IOVecWrapper vec = IOVecWrapper.get(length);
 
-        // Create shadow to ensure DirectByteBuffers are used
-        ByteBuffer[] shadow = new ByteBuffer[numBufs];
+        boolean completed = false;
+        int iov_len = 0;
         try {
-            for (int i=0; i<numBufs; i++) {
-                if (!(bufs[i] instanceof DirectBuffer)) {
-                    int pos = bufs[i].position();
-                    int lim = bufs[i].limit();
-                    assert (pos <= lim);
-                    int rem = (pos <= lim ? lim - pos : 0);
 
-                    ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
-                    shadow[i] = bb;
-                    // Leave slow buffer position untouched; it will be updated
-                    // after we see how many bytes were really written out
-                    bb.put(bufs[i]);
-                    bufs[i].position(pos);
-                    bb.flip();
-                } else {
-                    shadow[i] = bufs[i];
+            // Iterate over buffers to populate native iovec array.
+            int count = offset + length;
+            for (int i=offset; i<count; i++) {
+                ByteBuffer buf = bufs[i];
+                int pos = buf.position();
+                int lim = buf.limit();
+                assert (pos <= lim);
+                int rem = (pos <= lim ? lim - pos : 0);
+                if (rem > 0) {
+                    vec.setBuffer(iov_len, buf, pos, rem);
+
+                    // allocate shadow buffer to ensure I/O is done with direct buffer
+                    if (!(buf instanceof DirectBuffer)) {
+                        ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
+                        shadow.put(buf);
+                        shadow.flip();
+                        vec.setShadow(iov_len, shadow);
+                        buf.position(pos);  // temporarily restore position in user buffer
+                        buf = shadow;
+                        pos = shadow.position();
+                    }
+
+                    vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
+                    vec.putLen(iov_len, rem);
+                    iov_len++;
                 }
             }
+            if (iov_len == 0)
+                return 0L;
 
-            IOVecWrapper vec = null;
-            long bytesWritten = 0;
-            try {
-                // Create a native iovec array
-                vec= new IOVecWrapper(numBufs);
-
-                // Fill in the iovec array with appropriate data
-                for (int i=0; i<numBufs; i++) {
-                    ByteBuffer nextBuffer = shadow[i];
-                    // put in the buffer addresses
-                    long pos = nextBuffer.position();
-                    long len = nextBuffer.limit() - pos;
-                    vec.putBase(i, ((DirectBuffer)nextBuffer).address() + pos);
-                    vec.putLen(i, len);
-                }
-
-                // Invoke native call to fill the buffers
-                bytesWritten = nd.writev(fd, vec.address, numBufs);
-            } finally {
-                vec.free();
-            }
-            long returnVal = bytesWritten;
+            long bytesWritten = nd.writev(fd, vec.address, iov_len);
 
             // Notify the buffers how many bytes were taken
-            for (int i=0; i<numBufs; i++) {
-                ByteBuffer nextBuffer = bufs[i];
-                int pos = nextBuffer.position();
-                int lim = nextBuffer.limit();
-                assert (pos <= lim);
-                int len = (pos <= lim ? lim - pos : lim);
-                if (bytesWritten >= len) {
-                    bytesWritten -= len;
-                    int newPosition = pos + len;
-                    nextBuffer.position(newPosition);
-                } else { // Buffers not completely filled
-                    if (bytesWritten > 0) {
-                        assert(pos + bytesWritten < (long)Integer.MAX_VALUE);
-                        int newPosition = (int)(pos + bytesWritten);
-                        nextBuffer.position(newPosition);
-                    }
-                    break;
+            long left = bytesWritten;
+            for (int j=0; j<iov_len; j++) {
+                if (left > 0) {
+                    ByteBuffer buf = vec.getBuffer(j);
+                    int pos = vec.getPosition(j);
+                    int rem = vec.getRemaining(j);
+                    int n = (left > rem) ? rem : (int)left;
+                    buf.position(pos + n);
+                    left -= n;
                 }
+                // return shadow buffers to buffer pool
+                ByteBuffer shadow = vec.getShadow(j);
+                if (shadow != null)
+                    Util.offerLastTemporaryDirectBuffer(shadow);
+                vec.clearRefs(j);
             }
-            return returnVal;
+
+            completed = true;
+            return bytesWritten;
+
         } finally {
-            // return any substituted buffers to cache
-            for (int i=0; i<numBufs; i++) {
-                ByteBuffer bb = shadow[i];
-                if (bb != null && bb != bufs[i]) {
-                    Util.releaseTemporaryDirectBuffer(bb);
+            // if an error occurred then clear refs to buffers and return any shadow
+            // buffers to cache
+            if (!completed) {
+                for (int j=0; j<iov_len; j++) {
+                    ByteBuffer shadow = vec.getShadow(j);
+                    if (shadow != null)
+                        Util.offerLastTemporaryDirectBuffer(shadow);
+                    vec.clearRefs(j);
                 }
             }
         }
@@ -231,7 +196,7 @@
                 dst.put(bb);
             return n;
         } finally {
-            Util.releaseTemporaryDirectBuffer(bb);
+            Util.offerFirstTemporaryDirectBuffer(bb);
         }
     }
 
@@ -262,92 +227,85 @@
     static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
         throws IOException
     {
-        int nextWithRemaining = remaining(bufs);
-        // if all bufs are empty we should return immediately
-        if (nextWithRemaining < 0)
-            return 0;
-        // If some bufs are empty we should skip them
-        if (nextWithRemaining > 0)
-            bufs = skipBufs(bufs, nextWithRemaining);
+        return read(fd, bufs, 0, bufs.length, nd);
+    }
 
-        int numBufs = bufs.length;
+    static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
+                     NativeDispatcher nd)
+        throws IOException
+    {
+        IOVecWrapper vec = IOVecWrapper.get(length);
 
-        // Read into the shadow to ensure DirectByteBuffers are used
-        ByteBuffer[] shadow = new ByteBuffer[numBufs];
-        boolean usingSlowBuffers = false;
+        boolean completed = false;
+        int iov_len = 0;
         try {
-            for (int i=0; i<numBufs; i++) {
-                if (bufs[i].isReadOnly())
+
+            // Iterate over buffers to populate native iovec array.
+            int count = offset + length;
+            for (int i=offset; i<count; i++) {
+                ByteBuffer buf = bufs[i];
+                if (buf.isReadOnly())
                     throw new IllegalArgumentException("Read-only buffer");
-                if (!(bufs[i] instanceof DirectBuffer)) {
-                    shadow[i] = Util.getTemporaryDirectBuffer(bufs[i].remaining());
-                    usingSlowBuffers = true;
-                } else {
-                    shadow[i] = bufs[i];
+                int pos = buf.position();
+                int lim = buf.limit();
+                assert (pos <= lim);
+                int rem = (pos <= lim ? lim - pos : 0);
+
+                if (rem > 0) {
+                    vec.setBuffer(iov_len, buf, pos, rem);
+
+                    // allocate shadow buffer to ensure I/O is done with direct buffer
+                    if (!(buf instanceof DirectBuffer)) {
+                        ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
+                        vec.setShadow(iov_len, shadow);
+                        buf = shadow;
+                        pos = shadow.position();
+                    }
+
+                    vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
+                    vec.putLen(iov_len, rem);
+                    iov_len++;
                 }
             }
+            if (iov_len == 0)
+                return 0L;
 
-            IOVecWrapper vec = null;
-            long bytesRead = 0;
-            try {
-                // Create a native iovec array
-                vec = new IOVecWrapper(numBufs);
-
-                // Fill in the iovec array with appropriate data
-                for (int i=0; i<numBufs; i++) {
-                    ByteBuffer nextBuffer = shadow[i];
-                    // put in the buffer addresses
-                    long pos = nextBuffer.position();
-                    long len = nextBuffer.remaining();
-                    vec.putBase(i, ((DirectBuffer)nextBuffer).address() + pos);
-                    vec.putLen(i, len);
-                }
-
-                // Invoke native call to fill the buffers
-                bytesRead = nd.readv(fd, vec.address, numBufs);
-            } finally {
-                vec.free();
-            }
-            long returnVal = bytesRead;
+            long bytesRead = nd.readv(fd, vec.address, iov_len);
 
             // Notify the buffers how many bytes were read
-            for (int i=0; i<numBufs; i++) {
-                ByteBuffer nextBuffer = shadow[i];
-                // Note: should this have been cached from above?
-                int pos = nextBuffer.position();
-                int len = nextBuffer.remaining();
-                if (bytesRead >= len) {
-                    bytesRead -= len;
-                    int newPosition = pos + len;
-                    nextBuffer.position(newPosition);
-                } else { // Buffers not completely filled
-                    if (bytesRead > 0) {
-                        assert(pos + bytesRead < (long)Integer.MAX_VALUE);
-                        int newPosition = (int)(pos + bytesRead);
-                        nextBuffer.position(newPosition);
+            long left = bytesRead;
+            for (int j=0; j<iov_len; j++) {
+                ByteBuffer shadow = vec.getShadow(j);
+                if (left > 0) {
+                    ByteBuffer buf = vec.getBuffer(j);
+                    int rem = vec.getRemaining(j);
+                    int n = (left > rem) ? rem : (int)left;
+                    if (shadow == null) {
+                        int pos = vec.getPosition(j);
+                        buf.position(pos + n);
+                    } else {
+                        shadow.limit(shadow.position() + n);
+                        buf.put(shadow);
                     }
-                    break;
+                    left -= n;
                 }
+                if (shadow != null)
+                    Util.offerLastTemporaryDirectBuffer(shadow);
+                vec.clearRefs(j);
             }
 
-            // Put results from shadow into the slow buffers
-            if (usingSlowBuffers) {
-                for (int i=0; i<numBufs; i++) {
-                    if (!(bufs[i] instanceof DirectBuffer)) {
-                        shadow[i].flip();
-                        bufs[i].put(shadow[i]);
-                    }
-                }
-            }
-            return returnVal;
+            completed = true;
+            return bytesRead;
+
         } finally {
-            // return any substituted buffers to cache
-            if (usingSlowBuffers) {
-                for (int i=0; i<numBufs; i++) {
-                    ByteBuffer bb = shadow[i];
-                    if (bb != null && bb != bufs[i]) {
-                        Util.releaseTemporaryDirectBuffer(bb);
-                    }
+            // if an error occurred then clear refs to buffers and return any shadow
+            // buffers to cache
+            if (!completed) {
+                for (int j=0; j<iov_len; j++) {
+                    ByteBuffer shadow = vec.getShadow(j);
+                    if (shadow != null)
+                        Util.offerLastTemporaryDirectBuffer(shadow);
+                    vec.clearRefs(j);
                 }
             }
         }
--- a/src/share/classes/sun/nio/ch/IOVecWrapper.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/sun/nio/ch/IOVecWrapper.java	Mon Aug 23 19:14:20 2010 -0700
@@ -25,6 +25,7 @@
 
 package sun.nio.ch;
 
+import java.nio.ByteBuffer;
 import sun.misc.*;
 
 
@@ -43,23 +44,98 @@
 class IOVecWrapper {
 
     // Miscellaneous constants
-    static int BASE_OFFSET = 0;
-    static int LEN_OFFSET;
-    static int SIZE_IOVEC;
+    private static final int BASE_OFFSET = 0;
+    private static final int LEN_OFFSET;
+    private static final int SIZE_IOVEC;
 
     // The iovec array
-    private AllocatedNativeObject vecArray;
+    private final AllocatedNativeObject vecArray;
+
+    // Number of elements in iovec array
+    private final int size;
+
+    // Buffers and position/remaining corresponding to elements in iovec array
+    private final ByteBuffer[] buf;
+    private final int[] position;
+    private final int[] remaining;
+
+    // Shadow buffers for cases when original buffer is substituted
+    private final ByteBuffer[] shadow;
 
     // Base address of this array
-    long address;
+    final long address;
 
     // Address size in bytes
     static int addressSize;
 
-    IOVecWrapper(int newSize) {
-        newSize = (newSize + 1) * SIZE_IOVEC;
-        vecArray = new AllocatedNativeObject(newSize, false);
-        address = vecArray.address();
+    private static class Deallocator implements Runnable {
+        private final AllocatedNativeObject obj;
+        Deallocator(AllocatedNativeObject obj) {
+            this.obj = obj;
+        }
+        public void run() {
+            obj.free();
+        }
+    }
+
+    // per thread IOVecWrapper
+    private static final ThreadLocal<IOVecWrapper> cached =
+        new ThreadLocal<IOVecWrapper>();
+
+    private IOVecWrapper(int size) {
+        this.size      = size;
+        this.buf       = new ByteBuffer[size];
+        this.position  = new int[size];
+        this.remaining = new int[size];
+        this.shadow    = new ByteBuffer[size];
+        this.vecArray  = new AllocatedNativeObject(size * SIZE_IOVEC, false);
+        this.address   = vecArray.address();
+    }
+
+    static IOVecWrapper get(int size) {
+        IOVecWrapper wrapper = cached.get();
+        if (wrapper != null && wrapper.size < size) {
+            // not big enough; eagerly release memory
+            wrapper.vecArray.free();
+            wrapper = null;
+        }
+        if (wrapper == null) {
+            wrapper = new IOVecWrapper(size);
+            Cleaner.create(wrapper, new Deallocator(wrapper.vecArray));
+            cached.set(wrapper);
+        }
+        return wrapper;
+    }
+
+    void setBuffer(int i, ByteBuffer buf, int pos, int rem) {
+        this.buf[i] = buf;
+        this.position[i] = pos;
+        this.remaining[i] = rem;
+    }
+
+    void setShadow(int i, ByteBuffer buf) {
+        shadow[i] = buf;
+    }
+
+    ByteBuffer getBuffer(int i) {
+        return buf[i];
+    }
+
+    int getPosition(int i) {
+        return position[i];
+    }
+
+    int getRemaining(int i) {
+        return remaining[i];
+    }
+
+    ByteBuffer getShadow(int i) {
+        return shadow[i];
+    }
+
+    void clearRefs(int i) {
+        buf[i] = null;
+        shadow[i] = null;
     }
 
     void putBase(int i, long base) {
@@ -78,10 +154,6 @@
             vecArray.putLong(offset, len);
     }
 
-    void free() {
-        vecArray.free();
-    }
-
     static {
         addressSize = Util.unsafe().addressSize();
         LEN_OFFSET = addressSize;
--- a/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Mon Aug 23 19:14:20 2010 -0700
@@ -385,9 +385,11 @@
         }
     }
 
-    private long read0(ByteBuffer[] bufs) throws IOException {
-        if (bufs == null)
-            throw new NullPointerException();
+    public long read(ByteBuffer[] dsts, int offset, int length)
+        throws IOException
+    {
+        if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
+            throw new IndexOutOfBoundsException();
         synchronized (readLock) {
             if (!ensureReadOpen())
                 return -1;
@@ -401,7 +403,7 @@
                 }
 
                 for (;;) {
-                    n = IOUtil.read(fd, bufs, nd);
+                    n = IOUtil.read(fd, dsts, offset, length, nd);
                     if ((n == IOStatus.INTERRUPTED) && isOpen())
                         continue;
                     return IOStatus.normalize(n);
@@ -418,15 +420,6 @@
         }
     }
 
-    public long read(ByteBuffer[] dsts, int offset, int length)
-        throws IOException
-    {
-        if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
-            throw new IndexOutOfBoundsException();
-        // ## Fix IOUtil.write so that we can avoid this array copy
-        return read0(Util.subsequence(dsts, offset, length));
-    }
-
     public int write(ByteBuffer buf) throws IOException {
         if (buf == null)
             throw new NullPointerException();
@@ -458,9 +451,11 @@
         }
     }
 
-    public long write0(ByteBuffer[] bufs) throws IOException {
-        if (bufs == null)
-            throw new NullPointerException();
+    public long write(ByteBuffer[] srcs, int offset, int length)
+        throws IOException
+    {
+        if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
+            throw new IndexOutOfBoundsException();
         synchronized (writeLock) {
             ensureWriteOpen();
             long n = 0;
@@ -472,7 +467,7 @@
                     writerThread = NativeThread.current();
                 }
                 for (;;) {
-                    n = IOUtil.write(fd, bufs, nd);
+                    n = IOUtil.write(fd, srcs, offset, length, nd);
                     if ((n == IOStatus.INTERRUPTED) && isOpen())
                         continue;
                     return IOStatus.normalize(n);
@@ -489,15 +484,6 @@
         }
     }
 
-    public long write(ByteBuffer[] srcs, int offset, int length)
-        throws IOException
-    {
-        if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
-            throw new IndexOutOfBoundsException();
-        // ## Fix IOUtil.write so that we can avoid this array copy
-        return write0(Util.subsequence(srcs, offset, length));
-    }
-
     // package-private
     int sendOutOfBandData(byte b) throws IOException {
         synchronized (writeLock) {
--- a/src/share/classes/sun/nio/ch/Util.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/classes/sun/nio/ch/Util.java	Mon Aug 23 19:14:20 2010 -0700
@@ -41,67 +41,180 @@
 
 class Util {
 
-
     // -- Caches --
 
     // The number of temp buffers in our pool
-    private static final int TEMP_BUF_POOL_SIZE = 3;
+    private static final int TEMP_BUF_POOL_SIZE = 8;
 
-    // Per-thread soft cache of the last temporary direct buffer
-    private static ThreadLocal<SoftReference<ByteBuffer>>[] bufferPool;
+    // Per-thread cache of temporary direct buffers
+    private static ThreadLocal<BufferCache> bufferCache =
+        new ThreadLocal<BufferCache>()
+    {
+        @Override
+        protected BufferCache initialValue() {
+            return new BufferCache();
+        }
+    };
 
-    @SuppressWarnings("unchecked")
-    static ThreadLocal<SoftReference<ByteBuffer>>[] createThreadLocalBufferPool() {
-        return new ThreadLocal[TEMP_BUF_POOL_SIZE];
-    }
+    /**
+     * A simple cache of direct buffers.
+     */
+    private static class BufferCache {
+        // the array of buffers
+        private ByteBuffer[] buffers;
 
-    static {
-        bufferPool = createThreadLocalBufferPool();
-        for (int i=0; i<TEMP_BUF_POOL_SIZE; i++)
-            bufferPool[i] = new ThreadLocal<SoftReference<ByteBuffer>>();
-    }
+        // the number of buffers in the cache
+        private int count;
 
-    static ByteBuffer getTemporaryDirectBuffer(int size) {
-        ByteBuffer buf = null;
-        // Grab a buffer if available
-        for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) {
-            SoftReference<ByteBuffer> ref = bufferPool[i].get();
-            if ((ref != null) && ((buf = ref.get()) != null) &&
-                (buf.capacity() >= size)) {
-                buf.rewind();
-                buf.limit(size);
-                bufferPool[i].set(null);
-                return buf;
+        // the index of the first valid buffer (undefined if count == 0)
+        private int start;
+
+        private int next(int i) {
+            return (i + 1) % TEMP_BUF_POOL_SIZE;
+        }
+
+        BufferCache() {
+            buffers = new ByteBuffer[TEMP_BUF_POOL_SIZE];
+        }
+
+        /**
+         * Removes and returns a buffer from the cache of at least the given
+         * size (or null if no suitable buffer is found).
+         */
+        ByteBuffer get(int size) {
+            if (count == 0)
+                return null;  // cache is empty
+
+            ByteBuffer[] buffers = this.buffers;
+
+            // search for suitable buffer (often the first buffer will do)
+            ByteBuffer buf = buffers[start];
+            if (buf.capacity() < size) {
+                buf = null;
+                int i = start;
+                while ((i = next(i)) != start) {
+                    ByteBuffer bb = buffers[i];
+                    if (bb == null)
+                        break;
+                    if (bb.capacity() >= size) {
+                        buf = bb;
+                        break;
+                    }
+                }
+                if (buf == null)
+                    return null;
+                // move first element to here to avoid re-packing
+                buffers[i] = buffers[start];
+            }
+
+            // remove first element
+            buffers[start] = null;
+            start = next(start);
+            count--;
+
+            // prepare the buffer and return it
+            buf.rewind();
+            buf.limit(size);
+            return buf;
+        }
+
+        boolean offerFirst(ByteBuffer buf) {
+            if (count >= TEMP_BUF_POOL_SIZE) {
+                return false;
+            } else {
+                start = (start + TEMP_BUF_POOL_SIZE - 1) % TEMP_BUF_POOL_SIZE;
+                buffers[start] = buf;
+                count++;
+                return true;
             }
         }
 
-        // Make a new one
-        return ByteBuffer.allocateDirect(size);
-    }
-
-    static void releaseTemporaryDirectBuffer(ByteBuffer buf) {
-        if (buf == null)
-            return;
-        // Put it in an empty slot if such exists
-        for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) {
-            SoftReference<ByteBuffer> ref = bufferPool[i].get();
-            if ((ref == null) || (ref.get() == null)) {
-                bufferPool[i].set(new SoftReference<ByteBuffer>(buf));
-                return;
-            }
-        }
-        // Otherwise replace a smaller one in the cache if such exists
-        for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) {
-            SoftReference<ByteBuffer> ref = bufferPool[i].get();
-            ByteBuffer inCacheBuf = ref.get();
-            if ((inCacheBuf == null) || (buf.capacity() > inCacheBuf.capacity())) {
-                bufferPool[i].set(new SoftReference<ByteBuffer>(buf));
-                return;
+        boolean offerLast(ByteBuffer buf) {
+            if (count >= TEMP_BUF_POOL_SIZE) {
+                return false;
+            } else {
+                int next = (start + count) % TEMP_BUF_POOL_SIZE;
+                buffers[next] = buf;
+                count++;
+                return true;
             }
         }
 
-        // release memory
-       ((DirectBuffer)buf).cleaner().clean();
+        boolean isEmpty() {
+            return count == 0;
+        }
+
+        ByteBuffer removeFirst() {
+            assert count > 0;
+            ByteBuffer buf = buffers[start];
+            buffers[start] = null;
+            start = next(start);
+            count--;
+            return buf;
+        }
+    }
+
+    /**
+     * Returns a temporary buffer of at least the given size
+     */
+    static ByteBuffer getTemporaryDirectBuffer(int size) {
+        BufferCache cache = bufferCache.get();
+        ByteBuffer buf = cache.get(size);
+        if (buf != null) {
+            return buf;
+        } else {
+            // No suitable buffer in the cache so we need to allocate a new
+            // one. To avoid the cache growing then we remove the first
+            // buffer from the cache and free it.
+            if (!cache.isEmpty()) {
+                buf = cache.removeFirst();
+                free(buf);
+            }
+            return ByteBuffer.allocateDirect(size);
+        }
+    }
+
+    /**
+     * Releases a temporary buffer by returning to the cache or freeing it.
+     */
+    static void releaseTemporaryDirectBuffer(ByteBuffer buf) {
+        offerFirstTemporaryDirectBuffer(buf);
+    }
+
+    /**
+     * Releases a temporary buffer by returning to the cache or freeing it. If
+     * returning to the cache then insert it at the start so that it is
+     * likely to be returned by a subsequent call to getTemporaryDirectBuffer.
+     */
+    static void offerFirstTemporaryDirectBuffer(ByteBuffer buf) {
+        assert buf != null;
+        BufferCache cache = bufferCache.get();
+        if (!cache.offerFirst(buf)) {
+            // cache is full
+            free(buf);
+        }
+    }
+
+    /**
+     * Releases a temporary buffer by returning to the cache or freeing it. If
+     * returning to the cache then insert it at the end. This makes it
+     * suitable for scatter/gather operations where the buffers are returned to
+     * cache in same order that they were obtained.
+     */
+    static void offerLastTemporaryDirectBuffer(ByteBuffer buf) {
+        assert buf != null;
+        BufferCache cache = bufferCache.get();
+        if (!cache.offerLast(buf)) {
+            // cache is full
+            free(buf);
+        }
+    }
+
+    /**
+     * Frees the memory for the given direct buffer
+     */
+    private static void free(ByteBuffer buf) {
+        ((DirectBuffer)buf).cleaner().clean();
     }
 
     private static class SelectorWrapper {
--- a/src/share/lib/security/java.security-solaris	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/lib/security/java.security-solaris	Mon Aug 23 19:14:20 2010 -0700
@@ -260,3 +260,30 @@
 # Example,
 #   ocsp.responderCertSerialNumber=2A:FF:00
  
+#
+# Policy for failed Kerberos KDC lookups:
+#
+# When a KDC is unavailable (network error, service failure, etc), it is
+# put inside a blacklist and accessed less often for future requests. The
+# value (case-insensitive) for this policy can be:
+#
+# tryLast
+#    KDCs in the blacklist are always tried after those not on the list.
+#
+# tryLess[:max_retries,timeout]
+#    KDCs in the blacklist are still tried by their order in the configuration,
+#    but with smaller max_retries and timeout values. max_retries and timeout
+#    are optional numerical parameters (default 1 and 5000, which means once
+#    and 5 seconds). Please notes that if any of the values defined here is
+#    more than what is defined in krb5.conf, it will be ignored.
+#
+# Whenever a KDC is detected as available, it is removed from the blacklist.
+# The blacklist is reset when krb5.conf is reloaded. You can add
+# refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is
+# reloaded whenever a JAAS authentication is attempted.
+#
+# Example,
+#   krb5.kdc.bad.policy = tryLast
+#   krb5.kdc.bad.policy = tryLess:2,2000
+krb5.kdc.bad.policy = tryLast
+
--- a/src/share/lib/security/java.security-windows	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/lib/security/java.security-windows	Mon Aug 23 19:14:20 2010 -0700
@@ -260,3 +260,30 @@
 # Example,
 #   ocsp.responderCertSerialNumber=2A:FF:00
  
+#
+# Policy for failed Kerberos KDC lookups:
+#
+# When a KDC is unavailable (network error, service failure, etc), it is
+# put inside a blacklist and accessed less often for future requests. The
+# value (case-insensitive) for this policy can be:
+#
+# tryLast
+#    KDCs in the blacklist are always tried after those not on the list.
+#
+# tryLess[:max_retries,timeout]
+#    KDCs in the blacklist are still tried by their order in the configuration,
+#    but with smaller max_retries and timeout values. max_retries and timeout
+#    are optional numerical parameters (default 1 and 5000, which means once
+#    and 5 seconds). Please notes that if any of the values defined here is
+#    more than what is defined in krb5.conf, it will be ignored.
+#
+# Whenever a KDC is detected as available, it is removed from the blacklist.
+# The blacklist is reset when krb5.conf is reloaded. You can add
+# refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is
+# reloaded whenever a JAAS authentication is attempted.
+#
+# Example,
+#   krb5.kdc.bad.policy = tryLast
+#   krb5.kdc.bad.policy = tryLess:2,2000
+krb5.kdc.bad.policy = tryLast
+
--- a/src/share/native/common/check_code.c	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/share/native/common/check_code.c	Mon Aug 23 19:14:20 2010 -0700
@@ -2730,7 +2730,10 @@
                                                                 operand);
             const char *result_signature;
             check_and_push(context, signature, VM_STRING_UTF);
-            result_signature = strchr(signature, JVM_SIGNATURE_ENDFUNC) + 1;
+            result_signature = strchr(signature, JVM_SIGNATURE_ENDFUNC);
+            if (result_signature++ == NULL) {
+                CCerror(context, "Illegal signature %s", signature);
+            }
             if (result_signature[0] == JVM_SIGNATURE_VOID) {
                 stack_results = "";
             } else {
@@ -3654,14 +3657,13 @@
                        const char **signature_p, fullinfo_type *full_info_p)
 {
     const char *p = *signature_p;
-    fullinfo_type full_info = MAKE_FULLINFO(0, 0, 0);
+    fullinfo_type full_info = MAKE_FULLINFO(ITEM_Bogus, 0, 0);
     char result;
     int array_depth = 0;
 
     for (;;) {
         switch(*p++) {
             default:
-                full_info = MAKE_FULLINFO(ITEM_Bogus, 0, 0);
                 result = 0;
                 break;
 
@@ -3714,7 +3716,14 @@
                 char buffer_space[256];
                 char *buffer = buffer_space;
                 char *finish = strchr(p, JVM_SIGNATURE_ENDCLASS);
-                int length = finish - p;
+                int length;
+                if (finish == NULL) {
+                    /* Signature must have ';' after the class name.
+                     * If it does not, return 0 and ITEM_Bogus in full_info. */
+                    result = 0;
+                    break;
+                }
+                length = finish - p;
                 if (length + 1 > (int)sizeof(buffer_space)) {
                     buffer = malloc(length + 1);
                     check_and_push(context, buffer, VM_MALLOC_BLK);
--- a/src/solaris/classes/java/io/UnixFileSystem.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/solaris/classes/java/io/UnixFileSystem.java	Mon Aug 23 19:14:20 2010 -0700
@@ -187,7 +187,6 @@
                     }
                 }
             }
-            assert canonicalize0(path).equals(res) || path.startsWith(javaHome);
             return res;
         }
     }
--- a/src/solaris/classes/sun/nio/fs/UnixPath.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/solaris/classes/sun/nio/fs/UnixPath.java	Mon Aug 23 19:14:20 2010 -0700
@@ -1141,6 +1141,13 @@
             }
             result = result.resolve(element);
         }
+
+        // check file exists (without following links)
+        try {
+            UnixFileAttributes.get(result, false);
+        } catch (UnixException x) {
+            x.rethrowAsIOException(result);
+        }
         return result;
     }
 
--- a/src/solaris/native/java/net/PlainDatagramSocketImpl.c	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/solaris/native/java/net/PlainDatagramSocketImpl.c	Mon Aug 23 19:14:20 2010 -0700
@@ -1052,30 +1052,38 @@
 Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env,
                                                            jobject this) {
     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
-    int fd;
-
-    int t = 1;
+    int fd, t = 1;
+#ifdef AF_INET6
+    int domain = ipv6_available() ? AF_INET6 : AF_INET;
+#else
+    int domain = AF_INET;
+#endif
 
     if (IS_NULL(fdObj)) {
         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
                         "Socket closed");
         return;
-    } else {
-#ifdef AF_INET6
-        if (ipv6_available()) {
-            fd =  JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
-        } else
-#endif /* AF_INET6 */
-            {
-                fd =  JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-            }
     }
-    if (fd == JVM_IO_ERR) {
+
+    if ((fd = JVM_Socket(domain, SOCK_DGRAM, 0)) == JVM_IO_ERR) {
         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
                        "Error creating socket");
         return;
     }
 
+#ifdef AF_INET6
+    /* Disable IPV6_V6ONLY to ensure dual-socket support */
+    if (domain == AF_INET6) {
+        int arg = 0;
+        if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
+                       sizeof(int)) < 0) {
+            NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
+            close(fd);
+            return;
+        }
+    }
+#endif /* AF_INET6 */
+
      setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char*) &t, sizeof(int));
 
 #ifdef __linux__
@@ -1088,7 +1096,7 @@
      * On Linux for IPv6 sockets we must set the hop limit
      * to 1 to be compatible with default ttl of 1 for IPv4 sockets.
      */
-    if (ipv6_available()) {
+    if (domain == AF_INET6) {
         int ttl = 1;
         setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&ttl,
                    sizeof(ttl));
--- a/src/solaris/native/java/net/PlainSocketImpl.c	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/solaris/native/java/net/PlainSocketImpl.c	Mon Aug 23 19:14:20 2010 -0700
@@ -181,6 +181,12 @@
                                            jboolean stream) {
     jobject fdObj, ssObj;
     int fd;
+    int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
+#ifdef AF_INET6
+    int domain = ipv6_available() ? AF_INET6 : AF_INET;
+#else
+    int domain = AF_INET;
+#endif
 
     if (socketExceptionCls == NULL) {
         jclass c = (*env)->FindClass(env, "java/net/SocketException");
@@ -194,25 +200,29 @@
         (*env)->ThrowNew(env, socketExceptionCls, "null fd object");
         return;
     }
-#ifdef AF_INET6
-    if (ipv6_available()) {
-        fd = JVM_Socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
-    } else
-#endif /* AF_INET6 */
-        {
-            fd = JVM_Socket(AF_INET, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
-        }
-    if (fd == JVM_IO_ERR) {
+
+    if ((fd = JVM_Socket(domain, type, 0)) == JVM_IO_ERR) {
         /* note: if you run out of fds, you may not be able to load
          * the exception class, and get a NoClassDefFoundError
          * instead.
          */
         NET_ThrowNew(env, errno, "can't create socket");
         return;
-    } else {
-        (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
     }
 
+#ifdef AF_INET6
+    /* Disable IPV6_V6ONLY to ensure dual-socket support */
+    if (domain == AF_INET6) {
+        int arg = 0;
+        if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
+                       sizeof(int)) < 0) {
+            NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
+            close(fd);
+            return;
+        }
+    }
+#endif /* AF_INET6 */
+
     /*
      * If this is a server socket then enable SO_REUSEADDR
      * automatically and set to non blocking.
@@ -221,9 +231,15 @@
     if (ssObj != NULL) {
         int arg = 1;
         SET_NONBLOCKING(fd);
-        JVM_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
-            sizeof(arg));
+        if (JVM_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
+                           sizeof(arg)) < 0) {
+            NET_ThrowNew(env, errno, "cannot set SO_REUSEADDR");
+            close(fd);
+            return;
+        }
     }
+
+    (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
 }
 
 /*
--- a/src/solaris/native/sun/nio/ch/Net.c	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/solaris/native/sun/nio/ch/Net.c	Mon Aug 23 19:14:20 2010 -0700
@@ -170,6 +170,22 @@
     if (fd < 0) {
         return handleSocketError(env, errno);
     }
+
+#ifdef AF_INET6
+    /* Disable IPV6_V6ONLY to ensure dual-socket support */
+    if (domain == AF_INET6) {
+        int arg = 0;
+        if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
+                       sizeof(int)) < 0) {
+            JNU_ThrowByNameWithLastError(env,
+                                         JNU_JAVANETPKG "SocketException",
+                                         "sun.nio.ch.Net.setIntOption");
+            close(fd);
+            return -1;
+        }
+    }
+#endif
+
     if (reuse) {
         int arg = 1;
         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
--- a/src/windows/classes/java/io/Win32FileSystem.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/src/windows/classes/java/io/Win32FileSystem.java	Mon Aug 23 19:14:20 2010 -0700
@@ -424,7 +424,6 @@
                     }
                 }
             }
-            assert canonicalize0(path).equalsIgnoreCase(res);
             return res;
         }
     }
--- a/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh	Mon Aug 23 19:13:15 2010 -0700
+++ b/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh	Mon Aug 23 19:14:20 2010 -0700
@@ -55,7 +55,7 @@
   Linux )
     FS="/"
     ;;
-  Windows* )
+  Windows* | CYGWIN* )
     FS="\\"
     ;;
 esac
--- a/test/java/net/URI/Test.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/test/java/net/URI/Test.java	Mon Aug 23 19:14:20 2010 -0700
@@ -1536,6 +1536,7 @@
         serial();
         urls();
         npes();
+        bugs();
     }
 
 
@@ -1572,6 +1573,19 @@
     }
 
 
+    // miscellaneous bugs/rfes that don't fit in with the test framework
+
+    static void bugs() {
+        // 6339649 - include detail message from nested exception
+        try {
+            URI uri = URI.create("http://nowhere.net/should not be permitted");
+        } catch (IllegalArgumentException e) {
+            if ("".equals(e.getMessage()) || e.getMessage() == null) {
+                throw new RuntimeException ("No detail message");
+            }
+        }
+    }
+
     public static void main(String[] args) throws Exception {
         switch (args.length) {
 
--- a/test/java/nio/file/Path/Misc.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/test/java/nio/file/Path/Misc.java	Mon Aug 23 19:14:20 2010 -0700
@@ -261,6 +261,21 @@
         assertTrue(file.toRealPath(true).isSameFile(file.toRealPath(false)));
 
         /**
+         * Test: toRealPath should fail if file does not exist
+         */
+        Path doesNotExist = dir.resolve("DoesNotExist");
+        try {
+            doesNotExist.toRealPath(true);
+            throw new RuntimeException("IOException expected");
+        } catch (IOException expected) {
+        }
+        try {
+            doesNotExist.toRealPath(false);
+            throw new RuntimeException("IOException expected");
+        } catch (IOException expected) {
+        }
+
+        /**
          * Test: toRealPath(true) should resolve links
          */
         if (supportsLinks) {
--- a/test/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.sh	Mon Aug 23 19:13:15 2010 -0700
+++ b/test/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.sh	Mon Aug 23 19:14:20 2010 -0700
@@ -23,6 +23,7 @@
 
 #
 # @test
+# @ignore until 6543856 is fixed
 # @bug 4990825
 # @summary attach to external but local JVM processes
 # @library ../../testlibrary
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/net/www/protocol/file/DirPermissionDenied.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+import java.net.URL;
+import java.net.URLConnection;
+import java.io.IOException;
+
+public class DirPermissionDenied {
+    public static void main(String[] args) throws Exception {
+        URL url = new URL("file:" + args[0]);
+
+        try {
+            URLConnection uc = url.openConnection();
+            uc.connect();
+        } catch (IOException e) {
+            // OK
+        } catch (Exception e) {
+            throw new RuntimeException("Failed " + e);
+        }
+
+        try {
+            URLConnection uc = url.openConnection();
+            uc.getInputStream();
+        } catch (IOException e) {
+            // OK
+        } catch (Exception e) {
+            throw new RuntimeException("Failed " + e);
+        }
+
+        try {
+            URLConnection uc = url.openConnection();
+            uc.getContentLengthLong();
+        } catch (IOException e) {
+            // OK
+        } catch (Exception e) {
+            throw new RuntimeException("Failed " + e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/net/www/protocol/file/DirPermissionDenied.sh	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,41 @@
+#
+# Copyright (c) 2010, 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 6977851
+# @summary NPE from FileURLConnection.connect
+# @build DirPermissionDenied
+# @run shell DirPermissionDenied.sh
+
+TESTDIR="${TESTCLASSES}/DirPermissionDeniedDirectory"
+echo ${TESTDIR}
+
+rm -rf ${TESTDIR}
+mkdir -p ${TESTDIR}
+chmod 333 ${TESTDIR}
+
+$TESTJAVA/bin/java -classpath $TESTCLASSES DirPermissionDenied ${TESTDIR}
+result=$?
+rm -rf ${TESTDIR}
+exit $result
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/BadKdcDefaultValue.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2010, 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 6976536
+ * @summary Solaris JREs do not have the krb5.kdc.bad.policy configured by default.
+ * @run main/othervm BadKdcDefaultValue
+ */
+
+import java.security.Security;
+
+public class BadKdcDefaultValue {
+    public static void main(String[] args) throws Exception {
+        if (!"tryLast".equalsIgnoreCase(
+                Security.getProperty("krb5.kdc.bad.policy"))) {
+            throw new Exception("Default value not correct");
+        }
+    }
+}
+
--- a/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/B6226610.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/B6226610.java	Mon Aug 23 19:14:20 2010 -0700
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 6226610
+ * @bug 6226610 6973030
  * @run main/othervm B6226610
  * @summary HTTP tunnel connections send user headers to proxy
  */
@@ -36,45 +36,23 @@
 
 import java.io.*;
 import java.net.*;
-import javax.net.ssl.*;
-import javax.net.ServerSocketFactory;
-import sun.net.www.*;
-import java.util.Enumeration;
+import sun.net.www.MessageHeader;
 
 public class B6226610 {
     static HeaderCheckerProxyTunnelServer proxy;
 
-    // it seems there's no proxy ever if a url points to 'localhost',
-    // even if proxy related properties are set. so we need to bind
-    // our simple http proxy and http server to a non-loopback address
-    static InetAddress firstNonLoAddress = null;
+    public static void main(String[] args) throws Exception
+    {
+        proxy = new HeaderCheckerProxyTunnelServer();
+        proxy.start();
 
-    public static void main(String[] args)
-    {
-       try {
-          proxy = new HeaderCheckerProxyTunnelServer();
-          proxy.start();
-       } catch (Exception e) {
-          System.out.println("Cannot create proxy: " + e);
-       }
-
-       try {
-            firstNonLoAddress = getNonLoAddress();
-
-            if (firstNonLoAddress == null) {
-                System.out.println("The test needs at least one non-loopback address to run. Quit now.");
-                System.exit(0);
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-
-        System.setProperty( "https.proxyHost", firstNonLoAddress.getHostAddress());
-        System.setProperty( "https.proxyPort", (new Integer(proxy.getLocalPort())).toString() );
+        String hostname = InetAddress.getLocalHost().getHostName();
 
         try {
-           URL u = new URL("https://" + firstNonLoAddress.getHostAddress());
-           java.net.URLConnection c = u.openConnection();
+           URL u = new URL("https://" + hostname + "/");
+           System.out.println("Connecting to " + u);
+           InetSocketAddress proxyAddr = new InetSocketAddress(hostname, proxy.getLocalPort());
+           java.net.URLConnection c = u.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddr));
 
            /* I want this header to go to the destination server only, protected
             * by SSL
@@ -89,33 +67,15 @@
             }
             else
                System.out.println(e);
-
+         } finally {
+             if (proxy != null) proxy.shutdown();
          }
 
          if (HeaderCheckerProxyTunnelServer.failed)
-            throw new RuntimeException("Test failed: Proxy should not receive user defined headers for tunneled requests");
+            throw new RuntimeException("Test failed; see output");
     }
-
-    public static InetAddress getNonLoAddress() throws Exception {
-        NetworkInterface loNIC = NetworkInterface.getByInetAddress(InetAddress.getByName("localhost"));
-        Enumeration<NetworkInterface> nics = NetworkInterface.getNetworkInterfaces();
-        while (nics.hasMoreElements()) {
-            NetworkInterface nic = nics.nextElement();
-            if (!nic.getName().equalsIgnoreCase(loNIC.getName())) {
-                Enumeration<InetAddress> addrs = nic.getInetAddresses();
-                while (addrs.hasMoreElements()) {
-                    InetAddress addr = addrs.nextElement();
-                    if (!addr.isLoopbackAddress())
-                        return addr;
-                }
-            }
-        }
-        return null;
-    }
-
 }
 
-
 class HeaderCheckerProxyTunnelServer extends Thread
 {
     public static boolean failed = false;
@@ -139,6 +99,10 @@
        }
     }
 
+    void shutdown() {
+        try { ss.close(); } catch (IOException e) {}
+    }
+
     public void run()
     {
         try {
@@ -178,6 +142,15 @@
            retrieveConnectInfo(statusLine);
 
            if (mheader.findValue("X-TestHeader") != null) {
+             System.out.println("Proxy should not receive user defined headers for tunneled requests");
+             failed = true;
+           }
+
+           // 6973030
+           String value;
+           if ((value = mheader.findValue("Proxy-Connection")) == null ||
+                !value.equals("keep-alive")) {
+             System.out.println("Proxy-Connection:keep-alive not being sent");
              failed = true;
            }
 
--- a/test/tools/jar/JarEntryTime.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/test/tools/jar/JarEntryTime.java	Mon Aug 23 19:14:20 2010 -0700
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 4225317
+ * @bug 4225317 6969651
  * @summary Check extracted files have date as per those in the .jar file
  */
 
@@ -68,17 +68,9 @@
     }
 
     public static void realMain(String[] args) throws Throwable {
-        final long now = System.currentTimeMillis();
-        final long earlier = now - (60L * 60L * 6L * 1000L);
-        final long yesterday = now - (60L * 60L * 24L * 1000L);
-
-        // ZipEntry's mod date has 2 seconds precision: give extra time to
-        // allow for e.g. rounding/truncation and networked/samba drives.
-        final long PRECISION = 10000L;
 
         File dirOuter = new File("outer");
         File dirInner = new File(dirOuter, "inner");
-
         File jarFile = new File("JarEntryTime.jar");
 
         // Remove any leftovers from prior run
@@ -99,6 +91,17 @@
         PrintWriter pw = new PrintWriter(fileInner);
         pw.println("hello, world");
         pw.close();
+
+        // Get the "now" from the "last-modified-time" of the last file we
+        // just created, instead of the "System.currentTimeMillis()", to
+        // workaround the possible "time difference" due to nfs.
+        final long now = fileInner.lastModified();
+        final long earlier = now - (60L * 60L * 6L * 1000L);
+        final long yesterday = now - (60L * 60L * 24L * 1000L);
+        // ZipEntry's mod date has 2 seconds precision: give extra time to
+        // allow for e.g. rounding/truncation and networked/samba drives.
+        final long PRECISION = 10000L;
+
         dirOuter.setLastModified(now);
         dirInner.setLastModified(yesterday);
         fileInner.setLastModified(earlier);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/CommandLineTests.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2007, 2010 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 CommandLineTests.sh
+ * @bug  6521334 6965836 6965836
+ * @compile -XDignore.symbol.file CommandLineTests.java Pack200Test.java
+ * @run main/timeout=1200 CommandLineTests
+ * @summary An ad hoc test to verify the behavior of pack200/unpack200 CLIs,
+ *           and a simulation of pack/unpacking in the install repo.
+ * @author ksrini
+ */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+/*
+ * We try a potpouri of things ie. we have pack.conf to setup some
+ * options as well as a couple of command line options. We also test
+ * the packing and unpacking mechanism using the Java APIs. This also
+ * simulates pack200 the install workspace, noting that this is a simulation
+ * and can only test jars that are guaranteed to be available, also the
+ * configuration may not be in sync with the installer workspace.
+ */
+
+public class CommandLineTests {
+    private static final File CWD = new File(".");
+    private static final File EXP_SDK = new File(CWD, "exp-sdk-image");
+    private static final File EXP_SDK_LIB_DIR = new File(EXP_SDK, "lib");
+    private static final File EXP_SDK_BIN_DIR = new File(EXP_SDK, "bin");
+    private static final File EXP_JRE_DIR = new File(EXP_SDK, "jre");
+    private static final File EXP_JRE_LIB_DIR = new File(EXP_JRE_DIR, "lib");
+    private static final File RtJar = new File(EXP_JRE_LIB_DIR, "rt.jar");
+    private static final File CharsetsJar = new File(EXP_JRE_LIB_DIR, "charsets.jar");
+    private static final File JsseJar = new File(EXP_JRE_LIB_DIR, "jsse.jar");
+    private static final File ToolsJar = new File(EXP_SDK_LIB_DIR, "tools.jar");
+    private static final File javaCmd;
+    private static final File javacCmd;
+    private static final File ConfigFile = new File("pack.conf");
+    private static final List<File> jarList;
+
+    static {
+        javaCmd = Utils.IsWindows
+                    ? new File(EXP_SDK_BIN_DIR, "java.exe")
+                    : new File(EXP_SDK_BIN_DIR, "java");
+
+        javacCmd = Utils.IsWindows
+                    ? new File(EXP_SDK_BIN_DIR, "javac.exe")
+                    : new File(EXP_SDK_BIN_DIR, "javac");
+
+        jarList = new ArrayList<File>();
+        jarList.add(RtJar);
+        jarList.add(CharsetsJar);
+        jarList.add(JsseJar);
+        jarList.add(ToolsJar);
+    }
+
+    // init test area with a copy of the sdk
+    static void init() throws IOException {
+            Utils.recursiveCopy(Utils.JavaSDK, EXP_SDK);
+            creatConfigFile();
+    }
+
+    // Hopefully, this should be kept in sync with what the installer does.
+    static void creatConfigFile() throws IOException {
+        FileOutputStream fos = null;
+        PrintStream ps = null;
+        try {
+            fos = new FileOutputStream(ConfigFile);
+            ps = new PrintStream(fos);
+            ps.println("com.sun.java.util.jar.pack.debug.verbose=0");
+            ps.println("pack.modification.time=keep");
+            ps.println("pack.keep.class.order=true");
+            ps.println("pack.deflate.hint=false");
+            // Fail the build, if new or unknown attributes are introduced.
+            ps.println("pack.unknown.attribute=error");
+            ps.println("pack.segment.limit=-1");
+            // BugId: 6328502,  These files will be passed-through as-is.
+            ps.println("pack.pass.file.0=java/lang/Error.class");
+            ps.println("pack.pass.file.1=java/lang/LinkageError.class");
+            ps.println("pack.pass.file.2=java/lang/Object.class");
+            ps.println("pack.pass.file.3=java/lang/Throwable.class");
+            ps.println("pack.pass.file.4=java/lang/VerifyError.class");
+            ps.println("pack.pass.file.5=com/sun/demo/jvmti/hprof/Tracker.class");
+        } finally {
+            Utils.close(ps);
+            Utils.close(fos);
+        }
+    }
+
+    static void runPack200(boolean jre) throws IOException {
+        List<String> cmdsList = new ArrayList<String>();
+        for (File f : jarList) {
+            if (jre && f.getName().equals("tools.jar")) {
+                continue;  // need not worry about tools.jar for JRE
+            }
+            // make a backup copy for re-use
+            File bakFile = new File(f.getName() + ".bak");
+            if (!bakFile.exists()) {  // backup
+                Utils.copyFile(f.getAbsoluteFile(), bakFile.getAbsoluteFile());
+            } else {  // restore
+                Utils.copyFile(bakFile.getAbsoluteFile(), f.getAbsoluteFile());
+            }
+            cmdsList.clear();
+            cmdsList.add(Utils.getPack200Cmd());
+            cmdsList.add("-J-esa");
+            cmdsList.add("-J-ea");
+            cmdsList.add(Utils.Is64Bit ? "-J-Xmx1g" : "-J-Xmx512m");
+            cmdsList.add("--repack");
+            cmdsList.add("--config-file=" + ConfigFile.getAbsolutePath());
+            if (jre) {
+                cmdsList.add("--strip-debug");
+            }
+            // NOTE: commented until 6965836 is fixed
+            // cmdsList.add("--code-attribute=StackMapTable=strip");
+            cmdsList.add(f.getAbsolutePath());
+            Utils.runExec(cmdsList);
+        }
+    }
+
+    static void testJRE() throws IOException {
+        runPack200(true);
+        // the speciment JRE
+        List<String> cmdsList = new ArrayList<String>();
+        cmdsList.add(javaCmd.getAbsolutePath());
+        cmdsList.add("-verify");
+        cmdsList.add("-version");
+        Utils.runExec(cmdsList);
+    }
+
+    static void testJDK() throws IOException {
+        runPack200(false);
+        // test the specimen JDK
+        List<String> cmdsList = new ArrayList<String>();
+        cmdsList.add(javaCmd.getAbsolutePath());
+        cmdsList.add("-verify");
+        cmdsList.add("-version");
+        Utils.runExec(cmdsList);
+
+        // invoke javac to test the tools.jar
+        cmdsList.clear();
+        cmdsList.add(javacCmd.getAbsolutePath());
+        cmdsList.add("-J-verify");
+        cmdsList.add("-help");
+        Utils.runExec(cmdsList);
+    }
+    public static void main(String... args) {
+        try {
+            init();
+            testJRE();
+            testJDK();
+        } catch (IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/Pack200Props.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2010, 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 6575373 6969063
+ * @summary verify default properties of the packer/unpacker and segment limit
+ * @compile -XDignore.symbol.file Utils.java Pack200Props.java
+ * @run main Pack200Props
+ * @author ksrini
+ */
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.Pack200;
+import java.util.jar.Pack200.Packer;
+
+/*
+ * Run this against a large jar file, by default the packer should generate only
+ * one segment, parse the output of the packer to verify if this is indeed true.
+ */
+
+public class Pack200Props {
+
+    public static void main(String... args) {
+        verifyDefaults();
+        File out = new File("test" + Utils.PACK_FILE_EXT);
+        out.delete();
+        verifySegmentLimit(out);
+    }
+
+    static void verifySegmentLimit(File outFile) {
+        File sdkHome = Utils.JavaSDK;
+        File testJar = new File(new File(sdkHome, "lib"), "tools.jar");
+
+        System.out.println("using pack200: " + Utils.getPack200Cmd());
+
+        List<String> cmdsList = new ArrayList<>();
+        cmdsList.add(Utils.getPack200Cmd());
+        cmdsList.add("--effort=1");
+        cmdsList.add("--verbose");
+        cmdsList.add("--no-gzip");
+        cmdsList.add(outFile.getName());
+        cmdsList.add(testJar.getAbsolutePath());
+        List<String> outList = Utils.runExec(cmdsList);
+
+        int count = 0;
+        for (String line : outList) {
+            System.out.println(line);
+            if (line.matches(".*Transmitted.*files of.*input bytes in a segment of.*bytes")) {
+                count++;
+            }
+        }
+        if (count == 0) {
+            throw new RuntimeException("no segments or no output ????");
+        } else if (count > 1) {
+            throw new RuntimeException("multiple segments detected, expected 1");
+        }
+    }
+
+    private static void verifyDefaults() {
+        Map<String, String> expectedDefaults = new HashMap<>();
+        Packer p = Pack200.newPacker();
+        expectedDefaults.put("com.sun.java.util.jar.pack.default.timezone",
+                p.FALSE);
+        expectedDefaults.put("com.sun.java.util.jar.pack.disable.native",
+                p.FALSE);
+        expectedDefaults.put("com.sun.java.util.jar.pack.verbose", "0");
+        expectedDefaults.put(p.CLASS_ATTRIBUTE_PFX + "CompilationID", "RUH");
+        expectedDefaults.put(p.CLASS_ATTRIBUTE_PFX + "SourceID", "RUH");
+        expectedDefaults.put(p.CODE_ATTRIBUTE_PFX + "CharacterRangeTable",
+                "NH[PHPOHIIH]");
+        expectedDefaults.put(p.CODE_ATTRIBUTE_PFX + "CoverageTable",
+                "NH[PHHII]");
+        expectedDefaults.put(p.DEFLATE_HINT, p.KEEP);
+        expectedDefaults.put(p.EFFORT, "5");
+        expectedDefaults.put(p.KEEP_FILE_ORDER, p.TRUE);
+        expectedDefaults.put(p.MODIFICATION_TIME, p.KEEP);
+        expectedDefaults.put(p.SEGMENT_LIMIT, "-1");
+        expectedDefaults.put(p.UNKNOWN_ATTRIBUTE, p.PASS);
+
+        Map<String, String> props = p.properties();
+        int errors = 0;
+        for (String key : expectedDefaults.keySet()) {
+            String def = expectedDefaults.get(key);
+            String x = props.get(key);
+            if (x == null) {
+                System.out.println("Error: key not found:" + key);
+                errors++;
+            } else {
+                if (!def.equals(x)) {
+                    System.out.println("Error: key " + key
+                            + "\n  value expected: " + def
+                            + "\n  value obtained: " + x);
+                    errors++;
+                }
+            }
+        }
+        if (errors > 0) {
+            throw new RuntimeException(errors +
+                    " error(s) encountered in default properties verification");
+        }
+    }
+}
+
--- a/test/tools/pack200/Pack200Simple.sh	Mon Aug 23 19:13:15 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +0,0 @@
-#
-# Copyright (c) 2003, 2007, 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 Pack200Simple.sh
-# @bug  6521334
-# @build Pack200Test
-# @run shell/timeout=1200 Pack200Simple.sh
-# @summary An ad hoc test to verify class-file format.
-# @author Kumar Srinivasan
-
-# The goal of this test is to assist javac or other developers 
-# who modify class file formats, to quickly test those modifications
-# without having to build the install workspace. However it must
-# be noted that building the install workspace is the only know
-# way to prevent build breakages.
-
-# Pack200 developers could use this  as a basic smoke-test, however 
-# please note, there are other more elaborate and  thorough tests for 
-# this very purpose. 
-
-# We try a potpouri of things ie. we have pack.conf to setup some 
-# options as well as a couple of command line options. We also test
-# the packing and unpacking mechanism using the Java APIs.
-
-# print error and exit with a message 
-errorOut() {
-  if [ "x$1" = "x" ]; then
-    printf "Error: Unknown error\n"
-  else
-    printf "Error: %s\n" "$1"
-  fi
-
-  exit 1
-}
-
-# Verify directory context variables are set
-if [ "${TESTJAVA}" = "" ]; then
-  errorOut "TESTJAVA not set.  Test cannot execute.  Failed."
-fi
-
-if [ "${TESTSRC}" = "" ]; then
-  errorOut "TESTSRC not set.  Test cannot execute.  Failed."
-fi
-
-
-if [ "${TESTCLASSES}" = "" ]; then
-  errorOut "TESTCLASSES not set.  Test cannot execute.  Failed."
-fi
-
-# The common java utils we need
-PACK200=${TESTJAVA}/bin/pack200
-UNPACK200=${TESTJAVA}/bin/unpack200
-JAR=${TESTJAVA}/bin/jar
-
-# For Windows and Linux needs the heap to be set, for others ergonomics
-# will do the rest. It is important to use ea, which can expose class
-# format errors much earlier than later.
-
-OS=`uname -s`
-
-
-case "$OS" in
-  Windows*|CYGWIN* )
-    PackOptions="-J-Xmx512m -J-ea"
-    break
-    ;;
-
-  Linux )
-    PackOptions="-J-Xmx512m -J-ea"
-    break
-    ;;
-
-  * )
-    PackOptions="-J-ea"
-    ;;
-esac
-
-# Creates a packfile of choice expects 1 argument the filename
-createConfigFile() {
- # optimize for speed
- printf "pack.effort=1\n" > $1
- # we DO want to know about new attributes
- printf "pack.unknown.attribute=error\n" >> $1
- # optimize for speed
- printf "pack.deflate.hint=false\n" >> $1
- # keep the ordering for easy compare
- printf "pack.keep.class.order=true\n" >> $1
-}
-
-
-# Tests a given jar, expects 1 argument the fully qualified
-# name to a test jar, it writes all output to the current
-# directory which is a scratch  area.
-testAJar() {
-  PackConf="pack.conf"
-  createConfigFile $PackConf
-
-  # Try some command line options
-  CLIPackOptions="$PackOptions -v --no-gzip --segment-limit=10000 --config-file=$PackConf"
-
-  jfName=`basename $1`
-
-  ${PACK200}   $CLIPackOptions  ${jfName}.pack $1 > ${jfName}.pack.log 2>&1
-  if [ $? != 0 ]; then
-    errorOut "$jfName packing failed"
-  fi
-
-  # We want to test unpack200, therefore we dont use -r with pack
-  ${UNPACK200} -v ${jfName}.pack $jfName > ${jfName}.unpack.log 2>&1
-  if [ $? != 0 ]; then
-    errorOut "$jfName unpacking failed"
-  fi
-
-  # A quick crc compare test to ensure a well formed zip
-  # archive, this is a critical unpack200 behaviour.
-
-  unzip -t $jfName > ${jfName}.unzip.log 2>&1 
-  if [ $? != 0 ]; then
-    errorOut "$jfName unzip -t test failed"
-  fi
-
-  # The PACK200 signature should be at the top of the log
-  # this tag is critical for deployment related tools.
-
-  head -5 ${jfName}.unzip.log | grep PACK200 > /dev/null 2>&1
-  if [ $? != 0 ]; then
-    errorOut "$jfName PACK200 signature missing"
-  fi
-
-
-  # we know  the size fields don't match, strip 'em out, its
-  # extremely important to ensure that the date stamps match up.
-  # Don't EVER sort the output we are checking for correct ordering.
-
-  ${JAR} -tvf $1 | sed -e 's/^ *[0-9]* //g'> ${jfName}.ref.txt
-  ${JAR} -tvf $jfName | sed -e 's/^ *[0-9]* //g'> ${jfName}.cmp.txt
-
-  diff ${jfName}.ref.txt ${jfName}.cmp.txt > ${jfName}.diff.log 2>&1
-  if [ $? != 0 ]; then
-    errorOut "$jfName files missing"
-  fi
-}
-
-# These JARs are the largest and also the most likely specimens to 
-# expose class format issues and stress the packer as well.
-
-JLIST="${TESTJAVA}/lib/tools.jar ${TESTJAVA}/jre/lib/rt.jar"
-
-
-# Test the Command Line Interfaces (CLI).
-mkdir cliTestDir 
-_pwd=`pwd`
-cd cliTestDir
-
-for jarfile in $JLIST ; do 
-  if [ -f $jarfile ]; then
-    testAJar $jarfile
-  else
-    errorOut "Error: '$jarFile' does not exist\nTest requires a j2sdk-image\n"
-  fi
-done
-cd $_pwd
-
-# Test the Java APIs.
-mkdir apiTestDir 
-_pwd=`pwd`
-cd  apiTestDir
-
-# Strip out the -J prefixes.
-JavaPackOptions=`printf %s "$PackOptions" | sed -e 's/-J//g'`
-
-# Test the Java APIs now.
-$TESTJAVA/bin/java $JavaPackOptions -cp $TESTCLASSES Pack200Test $JLIST || exit 1
-
-cd $_pwd
-
-exit 0
--- a/test/tools/pack200/Pack200Test.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/test/tools/pack200/Pack200Test.java	Mon Aug 23 19:14:20 2010 -0700
@@ -24,111 +24,97 @@
 
 import java.util.*;
 import java.io.*;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
 import java.util.jar.*;
-import java.util.zip.*;
 
-/*
- * Pack200Test.java
- *
- * @author ksrini
- */
+ /*
+  * @test
+  * @bug 6521334 6712743
+  * @summary check for memory leaks, test general packer/unpacker functionality\
+  *          using native and java unpackers
+  * @compile -XDignore.symbol.file Utils.java Pack200Test.java
+  * @run main/othervm/timeout=1200 -Xmx512m Pack200Test
+  * @author ksrini
+  */
 
 /**
- * These tests are very rudimentary smoke tests to ensure that the packing
- * unpacking process works on a select set of JARs.
+ * Tests the packing/unpacking via the APIs.
  */
 public class Pack200Test {
 
     private static ArrayList <File> jarList = new ArrayList<File>();
-    static final String PACKEXT = ".pack";
+    static final MemoryMXBean mmxbean = ManagementFactory.getMemoryMXBean();
+    static final long m0 = getUsedMemory();
+    static final int LEAK_TOLERANCE = 20000; // OS and GC related variations.
 
     /** Creates a new instance of Pack200Test */
     private Pack200Test() {}
 
-    private static void doPackUnpack() {
-        for (File in : jarList) {
-            Pack200.Packer packer = Pack200.newPacker();
-            Map<String, String> p = packer.properties();
-            // Take the time optimization vs. space
-            p.put(packer.EFFORT, "1");  // CAUTION: do not use 0.
-            // Make the memory consumption as effective as possible
-            p.put(packer.SEGMENT_LIMIT,"10000");
-            // throw an error if an attribute is unrecognized
-            p.put(packer.UNKNOWN_ATTRIBUTE, packer.ERROR);
-            // ignore all JAR deflation requests to save time
-            p.put(packer.DEFLATE_HINT, packer.FALSE);
-            // save the file ordering of the original JAR
-            p.put(packer.KEEP_FILE_ORDER, packer.TRUE);
+    static long getUsedMemory() {
+        mmxbean.gc();
+        mmxbean.gc();
+        mmxbean.gc();
+        return mmxbean.getHeapMemoryUsage().getUsed()/1024;
+    }
 
-            try {
-                JarFile jarFile = new JarFile(in);
-
-                // Write out to a jtreg scratch area
-                FileOutputStream fos = new FileOutputStream(in.getName() + PACKEXT);
-
-                System.out.print("Packing [" + in.toString() + "]...");
-                // Call the packer
-                packer.pack(jarFile, fos);
-                jarFile.close();
-                fos.close();
-
-                System.out.print("Unpacking...");
-                File f = new File(in.getName() + PACKEXT);
-
-                // Write out to current directory, jtreg will setup a scratch area
-                JarOutputStream jostream = new JarOutputStream(new FileOutputStream(in.getName()));
-
-                // Unpack the files
-                Pack200.Unpacker unpacker = Pack200.newUnpacker();
-                // Call the unpacker
-                unpacker.unpack(f, jostream);
-                // Must explicitly close the output.
-                jostream.close();
-                System.out.print("Testing...");
-                // Ok we have unpacked the file, lets test it.
-                doTest(in);
-                System.out.println("Done.");
-            } catch (Exception e) {
-                System.out.println("ERROR: " + e.getMessage());
-                System.exit(1);
-            }
+    private static void leakCheck() throws Exception {
+        long diff = getUsedMemory() - m0;
+        System.out.println("  Info: memory diff = " + diff + "K");
+        if ( diff  > LEAK_TOLERANCE) {
+            throw new Exception("memory leak detected " + diff);
         }
     }
 
-    private static ArrayList <String> getZipFileEntryNames(ZipFile z) {
-        ArrayList <String> out = new ArrayList<String>();
-        for (ZipEntry ze : Collections.list(z.entries())) {
-            out.add(ze.getName());
-        }
-        return out;
-    }
+    private static void doPackUnpack() {
+        for (File in : jarList) {
+            JarOutputStream javaUnpackerStream = null;
+            JarOutputStream nativeUnpackerStream = null;
+            JarFile jarFile = null;
+            try {
+                jarFile = new JarFile(in);
 
-    private static void doTest(File in) throws Exception {
-       // make sure all the files in the original jar exists in the other
-       ArrayList <String> refList = getZipFileEntryNames(new ZipFile(in));
-       ArrayList <String> cmpList = getZipFileEntryNames(new ZipFile(in.getName()));
+                // Write out to a jtreg scratch area
+                File packFile = new File(in.getName() + Utils.PACK_FILE_EXT);
 
-       System.out.print(refList.size() + "/" + cmpList.size() + " entries...");
+                System.out.println("Packing [" + in.toString() + "]");
+                // Call the packer
+                Utils.pack(jarFile, packFile);
+                jarFile.close();
+                leakCheck();
 
-       if (refList.size() != cmpList.size()) {
-           throw new Exception("Missing: files ?, entries don't match");
-       }
+                System.out.println("  Unpacking using java unpacker");
+                File javaUnpackedJar = new File("java-" + in.getName());
+                // Write out to current directory, jtreg will setup a scratch area
+                javaUnpackerStream = new JarOutputStream(
+                        new FileOutputStream(javaUnpackedJar));
+                Utils.unpackj(packFile, javaUnpackerStream);
+                javaUnpackerStream.close();
+                System.out.println("  Testing...java unpacker");
+                leakCheck();
+                // Ok we have unpacked the file, lets test it.
+                Utils.doCompareVerify(in.getAbsoluteFile(), javaUnpackedJar);
 
-       for (String ename: refList) {
-          if (!cmpList.contains(ename)) {
-              throw new Exception("Does not contain : " + ename);
-          }
-       }
-    }
-
-    private static void doSanity(String[] args) {
-        for (String s: args) {
-            File f = new File(s);
-            if (f.exists()) {
-                jarList.add(f);
-            } else {
-                System.out.println("Warning: The JAR file " + f.toString() + " does not exist,");
-                System.out.println("         this test requires a JDK image, this file will be skipped.");
+                System.out.println("  Unpacking using native unpacker");
+                // Write out to current directory
+                File nativeUnpackedJar = new File("native-" + in.getName());
+                nativeUnpackerStream = new JarOutputStream(
+                        new FileOutputStream(nativeUnpackedJar));
+                Utils.unpackn(packFile, nativeUnpackerStream);
+                nativeUnpackerStream.close();
+                System.out.println("  Testing...native unpacker");
+                leakCheck();
+                // the unpackers (native and java) should produce identical bits
+                // so we use use bit wise compare, the verification compare is
+                // very expensive wrt. time.
+                Utils.doCompareBitWise(javaUnpackedJar, nativeUnpackedJar);
+                System.out.println("Done.");
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            } finally {
+                Utils.close(nativeUnpackerStream);
+                Utils.close(javaUnpackerStream);
+                Utils.close((Closeable) jarFile);
             }
         }
     }
@@ -137,11 +123,12 @@
      * @param args the command line arguments
      */
     public static void main(String[] args) {
-        if (args.length < 1) {
-            System.out.println("Usage: jar1 jar2 jar3 .....");
-            System.exit(1);
-        }
-        doSanity(args);
+        // select the jars carefully, adding more jars will increase the
+        // testing time, especially for jprt.
+        jarList.add(Utils.locateJar("tools.jar"));
+        jarList.add(Utils.locateJar("rt.jar"));
+        jarList.add(Utils.locateJar("golden.jar"));
+        System.out.println(jarList);
         doPackUnpack();
     }
 }
--- a/test/tools/pack200/PackageVersionTest.java	Mon Aug 23 19:13:15 2010 -0700
+++ b/test/tools/pack200/PackageVersionTest.java	Mon Aug 23 19:14:20 2010 -0700
@@ -22,13 +22,14 @@
  * questions.
  */
 
-/**
-  * @test
-  * @bug 6712743
-  * @summary verify package versioning
-  * @compile -XDignore.symbol.file PackageVersionTest.java
-  * @run main PackageVersionTest
-  */
+/*
+ * @test
+ * @bug 6712743
+ * @summary verify package versions
+ * @compile -XDignore.symbol.file Utils.java PackageVersionTest.java
+ * @run main PackageVersionTest
+ * @author ksrini
+ */
 
 import java.io.ByteArrayOutputStream;
 import java.io.Closeable;
@@ -74,14 +75,6 @@
                 JAVA5_PACKAGE_MINOR_VERSION);
     }
 
-    static void close(Closeable c) {
-        if (c == null) {
-            return;
-        }
-        try {
-            c.close();
-        } catch (IOException ignore) {}
-    }
 
     static void createClassFile(String name) {
         createJavaFile(name);
@@ -93,7 +86,7 @@
             name.substring(name.length() - 1),
             name + ".java"
         };
-        compileJava(javacCmds);
+        Utils.compiler(javacCmds);
     }
 
     static void createJavaFile(String name) {
@@ -108,22 +101,8 @@
         } catch (IOException ioe) {
             throw new RuntimeException("creation of test file failed");
         } finally {
-            close(ps);
-            close(fos);
-        }
-    }
-
-    static void compileJava(String... javacCmds) {
-        if (com.sun.tools.javac.Main.compile(javacCmds) != 0) {
-            throw new RuntimeException("compilation failed");
-        }
-    }
-
-    static void makeJar(String... jargs) {
-        sun.tools.jar.Main jarTool =
-                new sun.tools.jar.Main(System.out, System.err, "jartool");
-        if (!jarTool.run(jargs)) {
-            throw new RuntimeException("jar command failed");
+            Utils.close(ps);
+            Utils.close(fos);
         }
     }
 
@@ -136,7 +115,7 @@
             jarFileName.getName(),
             filename
         };
-        makeJar(jargs);
+        Utils.jar(jargs);
         JarFile jfin = null;
 
         try {
@@ -163,7 +142,7 @@
         } catch (IOException ioe) {
             throw new RuntimeException(ioe.getMessage());
         } finally {
-            close(jfin);
+            Utils.close((Closeable) jfin);
         }
     }
 }
--- a/test/tools/pack200/SegmentLimit.java	Mon Aug 23 19:13:15 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-/*
- * Copyright (c) 2010, 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 6575373
- * @summary verify default segment limit
- * @compile SegmentLimit.java
- * @run main SegmentLimit
- */
-
-import java.io.BufferedReader;
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.PrintStream;
-
-/*
- * Run this against a large jar file, by default the packer should generate only
- * one segment, parse the output of the packer to verify if this is indeed true.
- */
-
-public class SegmentLimit {
-
-    private static final File  javaHome = new File(System.getProperty("java.home"));
-
-    public static void main(String... args) {
-        if (!javaHome.getName().endsWith("jre")) {
-            throw new RuntimeException("Error: requires an SDK to run");
-        }
-
-        File out = new File("test" + Pack200Test.PACKEXT);
-        out.delete();
-        runPack200(out);
-    }
-
-    static void close(Closeable c) {
-        if (c == null) {
-            return;
-        }
-        try {
-            c.close();
-        } catch (IOException ignore) {}
-    }
-
-    static void runPack200(File outFile) {
-        File binDir = new File(javaHome, "bin");
-        File pack200Exe = System.getProperty("os.name").startsWith("Windows")
-                ? new File(binDir, "pack200.exe")
-                : new File(binDir, "pack200");
-        File sdkHome = javaHome.getParentFile();
-        File testJar = new File(new File(sdkHome, "lib"), "tools.jar");
-
-        System.out.println("using pack200: " + pack200Exe.getAbsolutePath());
-
-        String[] cmds = { pack200Exe.getAbsolutePath(),
-                          "--effort=1",
-                          "--verbose",
-                          "--no-gzip",
-                          outFile.getName(),
-                          testJar.getAbsolutePath()
-        };
-        InputStream is = null;
-        BufferedReader br = null;
-        InputStreamReader ir = null;
-
-        FileOutputStream fos = null;
-        PrintStream ps = null;
-
-        try {
-            ProcessBuilder pb = new ProcessBuilder(cmds);
-            pb.redirectErrorStream(true);
-            Process p = pb.start();
-            is = p.getInputStream();
-            ir = new InputStreamReader(is);
-            br = new BufferedReader(ir);
-
-            File logFile = new File("pack200.log");
-            fos = new FileOutputStream(logFile);
-            ps  = new PrintStream(fos);
-
-            String line = br.readLine();
-            int count = 0;
-            while (line != null) {
-                line = line.trim();
-                if (line.matches(".*Transmitted.*files of.*input bytes in a segment of.*bytes")) {
-                    count++;
-                }
-                ps.println(line);
-                line=br.readLine();
-            }
-            p.waitFor();
-            if (p.exitValue() != 0) {
-                throw new RuntimeException("pack200 failed");
-            }
-            p.destroy();
-            if (count > 1) {
-                throw new Error("test fails: check for multiple segments(" +
-                        count + ") in: " + logFile.getAbsolutePath());
-            }
-        } catch (IOException ex) {
-            throw new RuntimeException(ex.getMessage());
-        } catch (InterruptedException ignore){
-        } finally {
-            close(is);
-            close(ps);
-            close(fos);
-        }
-    }
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/TimeStamp.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.TimeZone;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+
+/*
+ * @test
+ * @bug 6966740
+ * @summary verify identical timestamps, unpacked in any timezone
+ * @compile -XDignore.symbol.file Utils.java TimeStamp.java
+ * @run main/othervm TimeStamp
+ * @author ksrini
+ */
+
+/**
+ * First we pack the file in some time zone say India, then we unpack the  file
+ * in the current time zone, and ensure the timestamp recorded in the unpacked
+ * jar are the same.
+ */
+public class TimeStamp {
+    static final TimeZone tz = TimeZone.getDefault();
+
+
+    public static void main(String... args) throws IOException {
+
+        // make a local copy of our test file
+        File srcFile = Utils.locateJar("golden.jar");
+        File goldenFile = new File("golden.jar");
+        Utils.copyFile(srcFile, goldenFile.getAbsoluteFile());
+
+        JarFile goldenJarFile = new JarFile(goldenFile);
+        File packFile = new File("golden.pack");
+
+        // set the test timezone and pack the file
+        TimeZone.setDefault(TimeZone.getTimeZone("IST"));
+        Utils.pack(goldenJarFile, packFile);
+        TimeZone.setDefault(tz);   // reset the timezone
+
+        // unpack in the  test timezone
+        File istFile = new File("golden.jar.java.IST");
+        unpackJava(packFile, istFile);
+        verifyJar(goldenFile, istFile);
+        istFile.delete();
+
+        // unpack in some other timezone
+        File pstFile = new File("golden.jar.java.PST");
+        unpackJava(packFile, pstFile);
+        verifyJar(goldenFile, pstFile);
+        pstFile.delete();
+
+        // repeat the test for unpack200 tool.
+        istFile = new File("golden.jar.native.IST");
+        unpackNative(packFile, istFile);
+        verifyJar(goldenFile, istFile);
+        istFile.delete();
+
+        pstFile = new File("golden.jar.native.PST");
+        unpackNative(packFile, pstFile);
+        verifyJar(goldenFile, pstFile);
+        pstFile.delete();
+    }
+
+    static void unpackNative(File packFile, File outFile) {
+        String name = outFile.getName();
+        String tzname = name.substring(name.lastIndexOf(".") + 1);
+        HashMap<String, String> env = new HashMap<>();
+        switch(tzname) {
+            case "PST":
+                env.put("TZ", "US/Pacific");
+                break;
+            case "IST":
+                env.put("TZ", "Asia/Calcutta");
+                break;
+            default:
+                throw new RuntimeException("not implemented: " + tzname);
+        }
+        List<String> cmdsList = new ArrayList<>();
+        cmdsList.add(Utils.getUnpack200Cmd());
+        cmdsList.add(packFile.getName());
+        cmdsList.add(outFile.getName());
+        Utils.runExec(cmdsList, env);
+    }
+
+    static void unpackJava(File packFile, File outFile) throws IOException {
+        String name = outFile.getName();
+        String tzname = name.substring(name.lastIndexOf(".") + 1);
+        JarOutputStream jos = null;
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone(tzname));
+            jos = new JarOutputStream(new FileOutputStream(outFile));
+            System.out.println("Using timezone: " + TimeZone.getDefault());
+            Utils.unpackj(packFile, jos);
+        } finally {
+            Utils.close(jos);
+            TimeZone.setDefault(tz); // always reset
+        }
+    }
+
+    static void verifyJar(File f1, File f2) throws IOException {
+        int errors = 0;
+        JarFile jf1 = null;
+        JarFile jf2 = null;
+        try {
+            jf1 = new JarFile(f1);
+            jf2 = new JarFile(f2);
+            System.out.println("Verifying: " + f1 + " and " + f2);
+            for (JarEntry je1 : Collections.list(jf1.entries())) {
+                JarEntry je2 = jf2.getJarEntry(je1.getName());
+                if (je1.getTime() != je2.getTime()) {
+                    System.out.println("Error:");
+                    System.out.println("  expected:" + jf1.getName() + ":"
+                            + je1.getName() + ":" + je1.getTime());
+                    System.out.println("  obtained:" + jf2.getName() + ":"
+                            + je2.getName() + ":" + je2.getTime());
+                    errors++;
+                }
+            }
+        } finally {
+            Utils.close(jf1);
+            Utils.close(jf2);
+        }
+        if (errors > 0) {
+            throw new RuntimeException("FAIL:" + errors + " error(s) encounted");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/UnpackerMemoryTest.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2010, 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 6531345
+ * @summary check for unpacker memory leaks
+ * @compile -XDignore.symbol.file Utils.java UnpackerMemoryTest.java
+ * @run main/othervm/timeout=1200 -Xmx32m UnpackerMemoryTest
+ * @author ksrini
+ */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.io.IOException;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+
+public class UnpackerMemoryTest {
+
+    private static void createPackFile(File packFile) throws IOException {
+        File tFile = new File("test.dat");
+        FileOutputStream fos = null;
+        PrintStream ps = null;
+        String jarFileName = Utils.baseName(packFile, Utils.PACK_FILE_EXT)
+                + Utils.JAR_FILE_EXT;
+        JarFile jarFile = null;
+        try {
+            fos = new FileOutputStream(tFile);
+            ps = new PrintStream(fos);
+            ps.println("A quick brown fox");
+            Utils.jar("cvf", jarFileName, tFile.getName());
+            jarFile = new JarFile(jarFileName);
+            Utils.pack(jarFile, packFile);
+        } finally {
+            Utils.close(ps);
+            tFile.delete();
+            Utils.close(jarFile);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        String name = "foo";
+        File packFile = new File(name + Utils.PACK_FILE_EXT);
+        createPackFile(packFile);
+        if (!packFile.exists()) {
+           throw new RuntimeException(packFile + " not found");
+        }
+        File jarOut = new File(name + ".out");
+        for (int i = 0; i < 2000; i++) {
+            JarOutputStream jarOS = null;
+            FileOutputStream fos = null;
+            try {
+                fos = new FileOutputStream(jarOut);
+                jarOS = new JarOutputStream(fos);
+                System.out.println("Unpacking[" + i + "]" + packFile);
+                Utils.unpackn(packFile, jarOS);
+            }  finally {
+                Utils.close(jarOS);
+                Utils.close(fos);
+            }
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/Utils.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,516 @@
+/*
+ * Copyright (c) 2007, 2010 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.
+ */
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Pack200;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ *
+ * @author ksrini
+ */
+
+/*
+ * This class contains all the commonly used utilities used by various tests
+ * in this directory.
+ */
+class Utils {
+    static final String JavaHome = System.getProperty("test.java",
+            System.getProperty("java.home"));
+    static final boolean IsWindows =
+            System.getProperty("os.name").startsWith("Windows");
+    static final boolean Is64Bit =
+            System.getProperty("sun.arch.data.model", "32").equals("64");
+    static final File   JavaSDK =  new File(JavaHome).getParentFile();
+
+    static final String PACK_FILE_EXT   = ".pack";
+    static final String JAVA_FILE_EXT   = ".java";
+    static final String CLASS_FILE_EXT  = ".class";
+    static final String JAR_FILE_EXT    = ".jar";
+
+    static final File   TEST_SRC_DIR = new File(System.getProperty("test.src"));
+    static final String VERIFIER_DIR_NAME = "pack200-verifier";
+    static final File   VerifierJar = new File(VERIFIER_DIR_NAME + JAR_FILE_EXT);
+
+    private Utils() {} // all static
+
+    static {
+        if (!JavaHome.endsWith("jre")) {
+            throw new RuntimeException("Error: requires an SDK to run");
+        }
+    }
+
+    private static void init() throws IOException {
+        if (VerifierJar.exists()) {
+            return;
+        }
+        File srcDir = new File(TEST_SRC_DIR, VERIFIER_DIR_NAME);
+        List<File> javaFileList = findFiles(srcDir, createFilter(JAVA_FILE_EXT));
+        File tmpFile = File.createTempFile("javac", ".tmp");
+        File classesDir = new File("xclasses");
+        classesDir.mkdirs();
+        FileOutputStream fos = null;
+        PrintStream ps = null;
+        try {
+            fos = new FileOutputStream(tmpFile);
+            ps = new PrintStream(fos);
+            for (File f : javaFileList) {
+                ps.println(f.getAbsolutePath());
+            }
+        } finally {
+            close(ps);
+            close(fos);
+        }
+
+        compiler("-d",
+                "xclasses",
+                "@" + tmpFile.getAbsolutePath());
+
+        jar("cvfe",
+            VerifierJar.getName(),
+            "sun.tools.pack.verify.Main",
+            "-C",
+            "xclasses",
+            ".");
+    }
+
+    static void dirlist(File dir) {
+        File[] files = dir.listFiles();
+        System.out.println("--listing " + dir.getAbsolutePath() + "---");
+        for (File f : files) {
+            StringBuffer sb = new StringBuffer();
+            sb.append(f.isDirectory() ? "d " : "- ");
+            sb.append(f.getName());
+            System.out.println(sb);
+        }
+    }
+    static void doCompareVerify(File reference, File specimen) throws IOException {
+        init();
+        List<String> cmds = new ArrayList<String>();
+        cmds.add(getJavaCmd());
+        cmds.add("-jar");
+        cmds.add(VerifierJar.getName());
+        cmds.add(reference.getAbsolutePath());
+        cmds.add(specimen.getAbsolutePath());
+        cmds.add("-O");
+        runExec(cmds);
+    }
+
+    static void doCompareBitWise(File reference, File specimen)
+            throws IOException {
+        init();
+        List<String> cmds = new ArrayList<String>();
+        cmds.add(getJavaCmd());
+        cmds.add("-jar");
+        cmds.add(VerifierJar.getName());
+        cmds.add(reference.getName());
+        cmds.add(specimen.getName());
+        cmds.add("-O");
+        cmds.add("-b");
+        runExec(cmds);
+    }
+
+    static FileFilter createFilter(final String extension) {
+        return new FileFilter() {
+            @Override
+            public boolean accept(File pathname) {
+                String name = pathname.getName();
+                if (name.endsWith(extension)) {
+                    return true;
+                }
+                return false;
+            }
+        };
+    }
+
+    static final FileFilter DIR_FILTER = new FileFilter() {
+        public boolean accept(File pathname) {
+            if (pathname.isDirectory()) {
+                return true;
+            }
+            return false;
+        }
+    };
+
+    static final FileFilter FILE_FILTER = new FileFilter() {
+        public boolean accept(File pathname) {
+            if (pathname.isFile()) {
+                return true;
+            }
+            return false;
+        }
+    };
+
+    private static void setFileAttributes(File src, File dst) throws IOException {
+        dst.setExecutable(src.canExecute());
+        dst.setReadable(src.canRead());
+        dst.setWritable(src.canWrite());
+        dst.setLastModified(src.lastModified());
+    }
+
+    static void copyFile(File src, File dst) throws IOException {
+        if (src.isDirectory()) {
+            dst.mkdirs();
+            setFileAttributes(src, dst);
+            return;
+        } else {
+            File baseDirFile = dst.getParentFile();
+            if (!baseDirFile.exists()) {
+                baseDirFile.mkdirs();
+            }
+        }
+        FileInputStream in = null;
+        FileOutputStream out = null;
+        FileChannel srcChannel = null;
+        FileChannel dstChannel = null;
+        try {
+            in = new FileInputStream(src);
+            out = new FileOutputStream(dst);
+            srcChannel = in.getChannel();
+            dstChannel = out.getChannel();
+
+            long retval = srcChannel.transferTo(0, src.length(), dstChannel);
+            if (src.length() != dst.length()) {
+                throw new IOException("file copy failed for " + src);
+            }
+        } finally {
+            close(srcChannel);
+            close(dstChannel);
+            close(in);
+            close(out);
+        }
+        setFileAttributes(src, dst);
+    }
+
+    static String baseName(File file, String extension) {
+        return baseName(file.getAbsolutePath(), extension);
+    }
+
+    static String baseName(String name, String extension) {
+        int cut = name.length() - extension.length();
+        return name.lastIndexOf(extension) == cut
+                ? name.substring(0, cut)
+                : name;
+
+    }
+
+    /*
+     * Suppose a path is provided which consists of a full path
+     * this method returns the sub path for a full path ex: /foo/bar/baz/foobar.z
+     * and the base path is /foo/bar it will will return baz/foobar.z.
+     */
+    private static String getEntryPath(String basePath, String fullPath) {
+        if (!fullPath.startsWith(basePath)) {
+            return null;
+        }
+        return fullPath.substring(basePath.length());
+    }
+
+    static String getEntryPath(File basePathFile, File fullPathFile) {
+        return getEntryPath(basePathFile.toString(), fullPathFile.toString());
+    }
+
+    public static void recursiveCopy(File src, File dest) throws IOException {
+        if (!src.exists() || !src.canRead()) {
+            throw new IOException("file not found or readable: " + src);
+        }
+        if (dest.exists() && !dest.isDirectory() && !dest.canWrite()) {
+            throw new IOException("file not found or writeable: " + dest);
+        }
+        if (!dest.exists()) {
+            dest.mkdirs();
+        }
+        List<File> a = directoryList(src);
+        for (File f : a) {
+            copyFile(f, new File(dest, getEntryPath(src, f)));
+        }
+    }
+
+    static List<File> directoryList(File dirname) {
+        List<File>  dirList = new ArrayList<File>();
+        return directoryList(dirname, dirList, null);
+    }
+
+    private static List<File> directoryList(File dirname, List<File> dirList,
+            File[] dirs) {
+        dirList.addAll(Arrays.asList(dirname.listFiles(FILE_FILTER)));
+        dirs = dirname.listFiles(DIR_FILTER);
+        for (File f : dirs) {
+            if (f.isDirectory() && !f.equals(dirname)) {
+                dirList.add(f);
+                directoryList(f, dirList, dirs);
+            }
+        }
+        return dirList;
+    }
+
+    static void recursiveDelete(File dir) throws IOException {
+        if (dir.isFile()) {
+            dir.delete();
+        } else if (dir.isDirectory()) {
+            File[] entries = dir.listFiles();
+            for (int i = 0; i < entries.length; i++) {
+                if (entries[i].isDirectory()) {
+                    recursiveDelete(entries[i]);
+                }
+                entries[i].delete();
+            }
+            dir.delete();
+        }
+    }
+
+    static List<File> findFiles(File startDir, FileFilter filter)
+            throws IOException {
+        List<File> list = new ArrayList<File>();
+        findFiles0(startDir, list, filter);
+        return list;
+    }
+    /*
+     * finds files in the start directory using the the filter, appends
+     * the files to the dirList.
+     */
+    private static void findFiles0(File startDir, List<File> list,
+                                    FileFilter filter) throws IOException {
+        File[] foundFiles = startDir.listFiles(filter);
+        list.addAll(Arrays.asList(foundFiles));
+        File[] dirs = startDir.listFiles(DIR_FILTER);
+        for (File dir : dirs) {
+            findFiles0(dir, list, filter);
+        }
+    }
+
+    static void close(Closeable c) {
+        if (c == null) {
+            return;
+        }
+        try {
+            c.close();
+        } catch (IOException ignore) {
+        }
+    }
+
+    static void compiler(String... javacCmds) {
+        if (com.sun.tools.javac.Main.compile(javacCmds) != 0) {
+            throw new RuntimeException("compilation failed");
+        }
+    }
+
+    static void jar(String... jargs) {
+        sun.tools.jar.Main jarTool =
+                new sun.tools.jar.Main(System.out, System.err, "jartool");
+        if (!jarTool.run(jargs)) {
+            throw new RuntimeException("jar command failed");
+        }
+    }
+
+    // given a jar file foo.jar will write to foo.pack
+    static void pack(JarFile jarFile, File packFile) throws IOException {
+        Pack200.Packer packer = Pack200.newPacker();
+        Map<String, String> p = packer.properties();
+        // Take the time optimization vs. space
+        p.put(packer.EFFORT, "1");  // CAUTION: do not use 0.
+        // Make the memory consumption as effective as possible
+        p.put(packer.SEGMENT_LIMIT, "10000");
+        // ignore all JAR deflation requests to save time
+        p.put(packer.DEFLATE_HINT, packer.FALSE);
+        // save the file ordering of the original JAR
+        p.put(packer.KEEP_FILE_ORDER, packer.TRUE);
+        FileOutputStream fos = null;
+        try {
+            // Write out to a jtreg scratch area
+            fos = new FileOutputStream(packFile);
+            // Call the packer
+            packer.pack(jarFile, fos);
+        } finally {
+            close(fos);
+        }
+    }
+
+    // uses java unpacker, slow but useful to discover issues with the packer
+    static void unpackj(File inFile, JarOutputStream jarStream)
+            throws IOException {
+        unpack0(inFile, jarStream, true);
+
+    }
+
+    // uses native unpacker using the java APIs
+    static void unpackn(File inFile, JarOutputStream jarStream)
+            throws IOException {
+        unpack0(inFile, jarStream, false);
+    }
+
+    // given a packed file, create the jar file in the current directory.
+    private static void unpack0(File inFile, JarOutputStream jarStream,
+            boolean useJavaUnpack) throws IOException {
+        // Unpack the files
+        Pack200.Unpacker unpacker = Pack200.newUnpacker();
+        Map<String, String> props = unpacker.properties();
+        if (useJavaUnpack) {
+            props.put("com.sun.java.util.jar.pack.disable.native", "true");
+        }
+        // Call the unpacker
+        unpacker.unpack(inFile, jarStream);
+    }
+
+    static byte[] getBuffer(ZipFile zf, ZipEntry ze) throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        byte buf[] = new byte[8192];
+        InputStream is = null;
+        try {
+            is = zf.getInputStream(ze);
+            int n = is.read(buf);
+            while (n > 0) {
+                baos.write(buf, 0, n);
+                n = is.read(buf);
+            }
+            return baos.toByteArray();
+        } finally {
+            close(is);
+        }
+    }
+
+    static ArrayList<String> getZipFileEntryNames(ZipFile z) {
+        ArrayList<String> out = new ArrayList<String>();
+        for (ZipEntry ze : Collections.list(z.entries())) {
+            out.add(ze.getName());
+        }
+        return out;
+    }
+    static List<String> runExec(List<String> cmdsList) {
+        return runExec(cmdsList, null);
+    }
+    static List<String> runExec(List<String> cmdsList, Map<String, String> penv) {
+        ArrayList<String> alist = new ArrayList<String>();
+        ProcessBuilder pb =
+                new ProcessBuilder(cmdsList);
+        Map<String, String> env = pb.environment();
+        if (penv != null && !penv.isEmpty()) {
+            env.putAll(penv);
+        }
+        pb.directory(new File("."));
+        dirlist(new File("."));
+        for (String x : cmdsList) {
+            System.out.print(x + " ");
+        }
+        System.out.println("");
+        int retval = 0;
+        Process p = null;
+        InputStreamReader ir = null;
+        BufferedReader rd = null;
+        InputStream is = null;
+        try {
+            pb.redirectErrorStream(true);
+            p = pb.start();
+            is = p.getInputStream();
+            ir = new InputStreamReader(is);
+            rd = new BufferedReader(ir, 8192);
+
+            String in = rd.readLine();
+            while (in != null) {
+                alist.add(in);
+                System.out.println(in);
+                in = rd.readLine();
+            }
+            retval = p.waitFor();
+            if (retval != 0) {
+                throw new RuntimeException("process failed with non-zero exit");
+            }
+        } catch (Exception ex) {
+            throw new RuntimeException(ex.getMessage());
+        } finally {
+            close(rd);
+            close(ir);
+            close(is);
+            if (p != null) {
+                p.destroy();
+            }
+        }
+        return alist;
+    }
+
+    static String getUnpack200Cmd() {
+        return getAjavaCmd("unpack200");
+    }
+
+    static String getPack200Cmd() {
+        return getAjavaCmd("pack200");
+    }
+
+    static String getJavaCmd() {
+        return getAjavaCmd("java");
+    }
+
+    static String getAjavaCmd(String cmdStr) {
+        File binDir = new File(JavaHome, "bin");
+        File unpack200File = IsWindows
+                ? new File(binDir, cmdStr + ".exe")
+                : new File(binDir, cmdStr);
+
+        String cmd = unpack200File.getAbsolutePath();
+        if (!unpack200File.canExecute()) {
+            throw new RuntimeException("please check" +
+                    cmd + " exists and is executable");
+        }
+        return cmd;
+    }
+
+    private static List<File> locaterCache = null;
+    // search the source dir and jdk dir for requested file and returns
+    // the first location it finds.
+    static File locateJar(String name) {
+        try {
+            if (locaterCache == null) {
+                locaterCache = new ArrayList<File>();
+                locaterCache.addAll(findFiles(TEST_SRC_DIR, createFilter(JAR_FILE_EXT)));
+                locaterCache.addAll(findFiles(JavaSDK, createFilter(JAR_FILE_EXT)));
+            }
+            for (File f : locaterCache) {
+                if (f.getName().equals(name)) {
+                    return f;
+                }
+            }
+            throw new IOException("file not found: " + name);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/pack200-verifier/data/README	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,45 @@
+The files contained in the golden.jar have been harvested from many
+different sources, some are hand-crafted invalid class files (odds directory),
+or from random JDK builds.
+
+Generally these files serve to ensure the integrity of the packer and unpacker
+by,
+   1. maximizing the test coverage.
+   2. exercising all the Bands in the pack200 specification.
+   2. testing the behavior of the packer with invalid classes.
+   3. testing the archive integrity, ordering and description (date, sizes,
+      CRC etc.)
+
+Build:
+To rebuild this JAR follow these steps:
+    1. unzip the golden.jar to some directory lets call it "example"
+    2. now we can add any directories with files into example.
+    2. run the script BUILDME.sh  as
+       % sh BUILDME.sh example
+
+Note: the BUILDME.sh is known to work on all Unix platforms as well as Windows
+      using Cygwin.
+
+The above will create two JAR files in the current directory,
+example.jar and example-cls.jar, now the example.jar can be used as the
+golden.jar.
+
+To ensure the JAR has been built correctly use jar -tvf and compare the
+results of the old jar and the newly built one, note that the compressed sizes
+may differ, however the timestamps etc. should be consistent.
+
+Test:
+    Basic:
+        % pack200 --repack test.jar golden.jar
+
+    Advanced:
+       Create a pack.conf as follows:
+       % cat pack.conf
+       com.sun.java.util.jar.pack.dump.bands=true
+
+       % pack200 --no-gzip --config-file=pack.conf \
+           --verbose golden.jar.pack golden.jar
+
+       This command will dump the Bands in a unique directory BD_XXXXXX,
+       one can inspect the directory to ensure all of the bands are being
+       generated. Familiarity of the  Pack200 specification is suggested.
\ No newline at end of file
Binary file test/tools/pack200/pack200-verifier/data/golden.jar has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/pack200-verifier/make/build.xml	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,59 @@
+<project name="PackageVerify" default="dist" basedir="..">
+  <!-- Requires ant 1.6.1+ and JDK 1.6+-->
+
+  <!-- set global properties for this build -->
+  <property name="src"      value="${basedir}/src"/>
+  <property name="build"    value="${basedir}/build"/>
+  <property name="dist"     value="${basedir}/dist"/>
+  <property name="make"     value="${basedir}/make"/>
+  <property name="classes"  value="${build}/classes"/>
+  <property name="api"      value="${build}/api"/>
+
+  <target name="init">
+    <!-- Create the time stamp -->
+    <tstamp/>
+    <!-- Create the build directory structure used by compile -->
+    <mkdir dir="${build}"/>
+    <mkdir dir="${dist}"/>
+    <mkdir dir="${classes}"/>
+    <mkdir dir="${api}"/>
+  </target>
+
+  <target name="compile" depends="init">
+    <!-- Compile the java code from ${src} into ${build} -->
+    <javac 
+	source="1.6"
+	srcdir="${src}"
+	destdir="${build}/classes"
+	verbose="no"
+	debug="on"
+    />
+  </target>
+
+  <target name="doc" depends="init, compile">
+      <javadoc
+        source="1.6"
+        sourcepath="${src}"
+        destdir="${api}"
+      />
+  </target>
+  <target name="dist" depends="compile, doc">
+    <!-- Put everything in jar file -->
+    <jar destfile="${dist}/pack200-verifier.jar">
+	<manifest>
+	   <attribute name="Main-Class" value="sun.tools.pack.verify.Main"/>
+	</manifest>
+	<fileset dir="${classes}"/>
+    </jar>
+    <zip destfile="dist/pack200-verifier-doc.zip">
+        <fileset dir="${api}"/>
+    </zip>
+  </target>
+
+  <target name="clean">
+    <!-- Delete the ${build} and ${dist} directory trees -->
+    <delete dir="${build}"/>
+    <delete dir="${dist}"/>
+  </target>
+
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/ClassCompare.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+package sun.tools.pack.verify;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+import xmlkit.*;
+
+public class ClassCompare {
+
+    /*
+     * @author ksrini
+     */
+    private static XMLKit.Element getXMLelement(InputStream is,
+            boolean ignoreUnkAttrs,
+            List<String> ignoreElements) throws IOException {
+
+        ClassReader cr = new ClassReader();
+        cr.keepOrder = false;
+        XMLKit.Element e = cr.readFrom(is);
+
+        if (ignoreElements != null) {
+            XMLKit.Filter filter = XMLKit.elementFilter(ignoreElements);
+            e.removeAllInTree(filter);
+        }
+
+        if (ignoreUnkAttrs == true) {
+            // This removes any unknown attributes
+            e.removeAllInTree(XMLKit.elementFilter("Attribute"));
+        }
+        return e;
+    }
+
+    private static String getXMLPrettyString(XMLKit.Element e) throws IOException {
+        StringWriter out = new StringWriter();
+        e.writePrettyTo(out);
+        return out.toString();
+    }
+
+    private static boolean compareClass0(JarFile jf1, JarFile jf2,
+            JarEntry je, boolean ignoreUnkAttrs,
+            List<String> ignoreElements)
+            throws IOException {
+
+        InputStream is1 = jf1.getInputStream(je);
+        InputStream is2 = jf2.getInputStream(je);
+
+        // First we try to compare the bits if they are the same
+        boolean bCompare = JarFileCompare.compareStreams(is1, is2);
+
+        // If they are the same there is nothing more to do.
+        if (bCompare) {
+            Globals.println("+++" + je.getName() + "+++\t"
+                    + "b/b:PASS");
+            return bCompare;
+        }
+        is1.close();
+        is2.close();
+
+        is1 = jf1.getInputStream(je);
+        is2 = jf2.getInputStream(je);
+
+
+        XMLKit.Element e1 = getXMLelement(is1, ignoreUnkAttrs, ignoreElements);
+        XMLKit.Element e2 = getXMLelement(is2, ignoreUnkAttrs, ignoreElements);
+
+        Globals.print("+++" + je.getName() + "+++\t"
+                + e1.size() + "/" + e1.size() + ":");
+
+        boolean result = true;
+
+        if (e1.equals(e2)) {
+            Globals.println("PASS");
+        } else {
+            Globals.println("FAIL");
+            Globals.log("Strings differs");
+            Globals.log(getXMLPrettyString(e1));
+            Globals.log("----------");
+            Globals.log(getXMLPrettyString(e2));
+            result = false;
+        }
+        return result;
+    }
+
+    /*
+     * Given two Class Paths could be jars the first being a reference
+     * will execute a series of comparisons on the classname  specified
+     * The className could be null in which case it will iterate through
+     * all the classes, otherwise it will compare one class and exit.
+     */
+    public static boolean compareClass(String jar1, String jar2,
+            String className, boolean ignoreUnkAttrs,
+            List<String> ignoreElements)
+            throws IOException {
+
+        Globals.println("Unknown attributes ignored:" + ignoreUnkAttrs);
+        if (ignoreElements != null) {
+            Globals.println(ignoreElements.toString());
+        }
+
+        JarFile jf1 = new JarFile(jar1);
+        JarFile jf2 = new JarFile(jar2);
+
+        boolean result = true;
+
+        if (className == null) {
+            for (JarEntry je1 : Collections.list((Enumeration<JarEntry>) jf1.entries())) {
+                if (je1.getName().endsWith(".class")) {
+                    JarEntry je2 = jf2.getJarEntry(je1.getName());
+                    boolean pf = compareClass0(jf1, jf2, je1, ignoreUnkAttrs, ignoreElements);
+                    if (result == true) {
+                        result = pf;
+                    }
+                }
+            }
+        } else {
+            JarEntry je1 = jf1.getJarEntry(className);
+            result = compareClass0(jf1, jf2, je1, ignoreUnkAttrs, ignoreElements);
+        }
+        if (result == false) {
+            throw new RuntimeException("Class structural comparison failure");
+        }
+        return result;
+    }
+
+    public static boolean compareClass(String jar1, String jar2,
+            String className) throws IOException {
+
+        Stack<String> s = new Stack();
+        if (Globals.ignoreDebugAttributes()) {
+            s = new Stack();
+            s.push("LocalVariable");
+            s.push("LocalVariableType");
+            s.push("LineNumber");
+            s.push("SourceFile");
+        }
+        return compareClass(jar1, jar2, className, Globals.ignoreUnknownAttributes(), s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/Globals.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+/*
+ * A collection of useful global utilities commonly used.
+ */
+package sun.tools.pack.verify;
+
+import java.io.*;
+import java.util.*;
+
+/*
+ * @author ksrini
+ */
+
+class Globals {
+
+    private static int errors = 0;
+    private static PrintWriter _pw = null;
+    private static String _logFileName = null;
+    private static final String DEFAULT_LOG_FILE = "verifier.log";
+    private static boolean _verbose = true;
+    private static boolean _ignoreJarDirectories = false;
+    private static boolean _checkJarClassOrdering = true;
+    private static boolean _bitWiseClassCompare = false;
+    // Ignore Deprecated, SourceFile and Synthetic
+    private static boolean _ignoreCompileAttributes = false;
+    // Ignore Debug Attributes LocalVariableTable, LocalVariableType,LineNumberTable
+    private static boolean _ignoreDebugAttributes = false;
+    private static boolean _ignoreUnknownAttributes = false;
+    private static boolean _validateClass = true;
+    private static Globals _instance = null;
+
+    static Globals getInstance() {
+        if (_instance == null) {
+            _instance = new Globals();
+            _verbose = (System.getProperty("sun.tools.pack.verify.verbose") == null)
+                    ? false : true;
+            _ignoreJarDirectories = (System.getProperty("ignoreJarDirectories") == null)
+                    ? false : true;
+        }
+        return _instance;
+    }
+
+    static boolean ignoreCompileAttributes() {
+        return _ignoreCompileAttributes;
+    }
+
+    static boolean ignoreDebugAttributes() {
+        return _ignoreDebugAttributes;
+    }
+
+    static boolean ignoreUnknownAttributes() {
+        return _ignoreUnknownAttributes;
+    }
+
+    static boolean ignoreJarDirectories() {
+        return _ignoreJarDirectories;
+    }
+
+    static boolean validateClass() {
+        return _validateClass;
+    }
+
+    static void setCheckJarClassOrdering(boolean flag) {
+        _checkJarClassOrdering = flag;
+    }
+
+    static boolean checkJarClassOrdering() {
+        return _checkJarClassOrdering;
+    }
+
+    static boolean bitWiseClassCompare() {
+        return _bitWiseClassCompare;
+    }
+
+    static boolean setBitWiseClassCompare(boolean flag) {
+        return _bitWiseClassCompare = flag;
+    }
+
+    public static boolean setIgnoreCompileAttributes(boolean flag) {
+        return _ignoreCompileAttributes = flag;
+    }
+
+    static boolean setIgnoreDebugAttributes(boolean flag) {
+        return _ignoreDebugAttributes = flag;
+    }
+
+    static boolean setIgnoreUnknownAttributes(boolean flag) {
+        return _ignoreUnknownAttributes = flag;
+    }
+
+    static boolean setValidateClass(boolean flag) {
+        return _validateClass = flag;
+    }
+
+    static int getErrors() {
+        return errors;
+    }
+
+    static void trace(String s) {
+        if (_verbose) {
+            println(s);
+        }
+    }
+
+    static void print(String s) {
+        _pw.print(s);
+    }
+
+    static void println(String s) {
+        _pw.println(s);
+    }
+
+    static void log(String s) {
+        errors++;
+        _pw.println("ERROR:" + s);
+    }
+
+    static void lognoln(String s) {
+        errors++;
+        _pw.print(s);
+    }
+
+    private static PrintWriter openFile(String fileName) {
+        //Lets create the directory if it does not exist.
+        File f = new File(fileName);
+        File baseDir = f.getParentFile();
+        if (baseDir != null && baseDir.exists() == false) {
+            baseDir.mkdirs();
+        }
+        try {
+            return new PrintWriter(new FileWriter(f), true);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static void closeFile() {
+        _pw.flush();
+        _pw.close();
+    }
+
+    static void printPropsToLog() {
+        println("Log started " + new Date(System.currentTimeMillis()));
+        print(System.getProperty("java.vm.version"));
+        println("\t" + System.getProperty("java.vm.name"));
+
+        println("System properties");
+        println("\tjava.home=" + System.getProperty("java.home"));
+        println("\tjava.class.version=" + System.getProperty("java.class.version"));
+        println("\tjava.class.path=" + System.getProperty("java.class.path"));
+        println("\tjava.ext.dirs=" + System.getProperty("java.ext.dirs"));
+        println("\tos.name=" + System.getProperty("os.name"));
+        println("\tos.arch=" + System.getProperty("os.arch"));
+        println("\tos.version=" + System.getProperty("os.version"));
+        println("\tuser.name=" + System.getProperty("user.name"));
+        println("\tuser.home=" + System.getProperty("user.home"));
+        println("\tuser.dir=" + System.getProperty("user.dir"));
+        println("\tLocale.getDefault=" + Locale.getDefault());
+        println("System properties end");
+    }
+
+    static void openLog(String s) {
+        _logFileName = (s != null) ? s : "." + File.separator + DEFAULT_LOG_FILE;
+        _logFileName = (new File(_logFileName).isDirectory())
+                ? _logFileName + File.separator + DEFAULT_LOG_FILE : _logFileName;
+        _pw = openFile(_logFileName);
+        printPropsToLog();
+    }
+
+    static void closeLog() {
+        closeFile();
+    }
+
+    static String getLogFileName() {
+        return _logFileName;
+    }
+
+    static void diffCharData(String s1, String s2) {
+        boolean diff = false;
+        char[] c1 = s1.toCharArray();
+        char[] c2 = s2.toCharArray();
+        if (c1.length != c2.length) {
+            diff = true;
+            Globals.log("Length differs: " + (c1.length - c2.length));
+        }
+        // Take the smaller of the two arrays to prevent Array...Exception
+        int minlen = (c1.length < c2.length) ? c1.length : c2.length;
+        for (int i = 0; i < c1.length; i++) {
+            if (c1[i] != c2[i]) {
+                diff = true;
+                Globals.lognoln("\t idx[" + i + "] 0x" + Integer.toHexString(c1[i]) + "<>" + "0x" + Integer.toHexString(c2[i]));
+                Globals.log(" -> " + c1[i] + "<>" + c2[i]);
+            }
+        }
+    }
+
+    static void diffByteData(String s1, String s2) {
+        boolean diff = false;
+        byte[] b1 = s1.getBytes();
+        byte[] b2 = s2.getBytes();
+
+        if (b1.length != b2.length) {
+            diff = true;
+            //(+) b1 is greater, (-) b2 is greater
+            Globals.log("Length differs diff: " + (b1.length - b2.length));
+        }
+        // Take the smaller of the two array to prevent Array...Exception
+        int minlen = (b1.length < b2.length) ? b1.length : b2.length;
+        for (int i = 0; i < b1.length; i++) {
+            if (b1[i] != b2[i]) {
+                diff = true;
+                Globals.log("\t" + "idx[" + i + "] 0x" + Integer.toHexString(b1[i]) + "<>" + "0x" + Integer.toHexString(b2[i]));
+            }
+        }
+    }
+
+    static void dumpToHex(String s) {
+        try {
+            dumpToHex(s.getBytes("UTF-8"));
+        } catch (UnsupportedEncodingException uce) {
+            throw new RuntimeException(uce);
+        }
+    }
+
+    static void dumpToHex(byte[] buffer) {
+        int linecount = 0;
+        byte[] b = new byte[16];
+        for (int i = 0; i < buffer.length; i += 16) {
+            if (buffer.length - i > 16) {
+                System.arraycopy(buffer, i, b, 0, 16);
+                print16Bytes(b, linecount);
+                linecount += 16;
+            } else {
+                System.arraycopy(buffer, i, b, 0, buffer.length - i);
+                for (int n = buffer.length - (i + 1); n < 16; n++) {
+                    b[n] = 0;
+                }
+                print16Bytes(b, linecount);
+                linecount += 16;
+            }
+        }
+        Globals.log("-----------------------------------------------------------------");
+    }
+
+    static void print16Bytes(byte[] buffer, int linecount) {
+        final int MAX = 4;
+        Globals.lognoln(paddedHexString(linecount, 4) + " ");
+
+        for (int i = 0; i < buffer.length; i += 2) {
+            int iOut = pack2Bytes2Int(buffer[i], buffer[i + 1]);
+            Globals.lognoln(paddedHexString(iOut, 4) + " ");
+        }
+
+        Globals.lognoln("| ");
+
+        StringBuilder sb = new StringBuilder(new String(buffer));
+
+        for (int i = 0; i < buffer.length; i++) {
+            if (Character.isISOControl(sb.charAt(i))) {
+                sb.setCharAt(i, '.');
+            }
+        }
+        Globals.log(sb.toString());
+    }
+
+    static int pack2Bytes2Int(byte b1, byte b2) {
+        int out = 0x0;
+        out += b1;
+        out <<= 8;
+        out &= 0x0000ffff;
+        out |= 0x000000ff & b2;
+        return out;
+    }
+
+    static String paddedHexString(int n, int max) {
+        char[] c = Integer.toHexString(n).toCharArray();
+        char[] out = new char[max];
+
+        for (int i = 0; i < max; i++) {
+            out[i] = '0';
+        }
+        int offset = (max - c.length < 0) ? 0 : max - c.length;
+        for (int i = 0; i < c.length; i++) {
+            out[offset + i] = c[i];
+        }
+        return new String(out);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/JarFileCompare.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+package sun.tools.pack.verify;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+
+class JarFileCompare {
+    /*
+     * @author ksrini
+     */
+
+    private static VerifyTreeSet getVerifyTreeSet(String jarPath) {
+        VerifyTreeSet vts = new VerifyTreeSet();
+        try {
+            JarFile j = new JarFile(jarPath);
+            for (JarEntry je : Collections.list((Enumeration<JarEntry>) j.entries())) {
+                if (!je.isDirectory()) { // totally ignore directories
+                    vts.add(je.getName());
+                }
+            }
+        } catch (IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+        return vts;
+    }
+
+    private static LinkedList getListOfClasses(String jarPath) {
+        LinkedList l = new LinkedList();
+        try {
+            JarFile j = new JarFile(jarPath);
+            for (JarEntry je : Collections.list((Enumeration<JarEntry>) j.entries())) {
+                if (!je.isDirectory() && je.getName().endsWith(".class")) {
+                    l.add(je.getName());
+                }
+            }
+        } catch (IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+        return l;
+    }
+
+    private static void jarDirectoryCompare(String jarPath1, String jarPath2) {
+        VerifyTreeSet vts1 = getVerifyTreeSet(jarPath1);
+        VerifyTreeSet vts2 = getVerifyTreeSet(jarPath2);
+
+        TreeSet diff1 = vts1.diff(vts2);
+        if (diff1.size() > 0) {
+            Globals.log("Left has the following entries that right does not have");
+            Globals.log(diff1.toString());
+        }
+        TreeSet diff2 = vts2.diff(vts1);
+        if (diff2.size() > 0) {
+            Globals.log("Right has the following entries that left does not have");
+            Globals.log(diff2.toString());
+        }
+        if (Globals.checkJarClassOrdering()) {
+            boolean error = false;
+            Globals.println("Checking Class Ordering");
+            LinkedList l1 = getListOfClasses(jarPath1);
+            LinkedList l2 = getListOfClasses(jarPath2);
+            if (l1.size() != l2.size()) {
+                error = true;
+                Globals.log("The number of classes differs");
+                Globals.log("\t" + l1.size() + "<>" + l2.size());
+            }
+            for (int i = 0; i < l1.size(); i++) {
+                String s1 = (String) l1.get(i);
+                String s2 = (String) l2.get(i);
+                if (s1.compareTo(s2) != 0) {
+                    error = true;
+                    Globals.log("Ordering differs at[" + i + "] = " + s1);
+                    Globals.log("\t" + s2);
+                }
+            }
+        }
+    }
+
+    /*
+     * Returns true if the two Streams are bit identical, and false if they
+     * are not, no further diagnostics
+     */
+    static boolean compareStreams(InputStream is1, InputStream is2) {
+
+        BufferedInputStream bis1 = new BufferedInputStream(is1, 8192);
+        BufferedInputStream bis2 = new BufferedInputStream(is2, 8192);
+        try {
+            int i1, i2;
+            int count = 0;
+            while ((i1 = bis1.read()) == (i2 = bis2.read())) {
+                count++;
+                if (i1 < 0) {
+                    // System.out.println("bytes read " + count);
+                    return true;  // got all the way to EOF
+                }
+            }
+            return false;  // reads returned dif
+
+        } catch (IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+    }
+
+    private static void checkEntry(JarFile jf1, JarFile jf2, JarEntry je) throws IOException {
+        InputStream is1 = jf1.getInputStream(je);
+        InputStream is2 = jf2.getInputStream(je);
+        if (is1 != null && is2 != null) {
+            if (!compareStreams(jf1.getInputStream(je), jf2.getInputStream(je))) {
+                Globals.println("+++" + je.getName() + "+++");
+                Globals.log("Error: File:" + je.getName()
+                        + " differs, use a diff util for further diagnostics");
+            }
+        } else {
+            Globals.println("+++" + je.getName() + "+++");
+            Globals.log("Error: File:" + je.getName() + " not found in " + jf2.getName());
+        }
+    }
+
+    /*
+     * Given two jar files we compare and see if the jarfiles have all the
+     * entries. The property ignoreJarDirectories is set to true by default
+     * which means that Directory entries in a jar may be ignore.
+     */
+    static void jarCompare(String jarPath1, String jarPath2) {
+        jarDirectoryCompare(jarPath1, jarPath2);
+
+        try {
+            JarFile jf1 = new JarFile(jarPath1);
+            JarFile jf2 = new JarFile(jarPath2);
+
+            int nclasses = 0;
+            int nentries = 0;
+            int entries_checked = 0;
+            int classes_checked = 0;
+
+            for (JarEntry je : Collections.list((Enumeration<JarEntry>) jf1.entries())) {
+                if (!je.isDirectory() && !je.getName().endsWith(".class")) {
+                    nentries++;
+                } else if (je.getName().endsWith(".class")) {
+                    nclasses++;
+                }
+            }
+
+            for (JarEntry je : Collections.list((Enumeration<JarEntry>) jf1.entries())) {
+                if (je.isDirectory()) {
+                    continue;  // Ignore directories
+                }
+                if (!je.getName().endsWith(".class")) {
+                    entries_checked++;
+                    if (je.getName().compareTo("META-INF/MANIFEST.MF") == 0) {
+                        Manifest mf1 = new Manifest(jf1.getInputStream(je));
+                        Manifest mf2 = new Manifest(jf2.getInputStream(je));
+                        if (!mf1.equals(mf2)) {
+                            Globals.log("Error: Manifests differ");
+                            Globals.log("Manifest1");
+                            Globals.log(mf1.getMainAttributes().entrySet().toString());
+                            Globals.log("Manifest2");
+                            Globals.log(mf2.getMainAttributes().entrySet().toString());
+                        }
+                    } else {
+                        checkEntry(jf1, jf2, je);
+                    }
+                } else if (Globals.bitWiseClassCompare() == true) {
+                    checkEntry(jf1, jf2, je);
+                    classes_checked++;
+                }
+            }
+            if (Globals.bitWiseClassCompare()) {
+                Globals.println("Class entries checked (byte wise)/Total Class entries = "
+                        + classes_checked + "/" + nclasses);
+            }
+            Globals.println("Non-class entries checked/Total non-class entries = "
+                    + entries_checked + "/" + nentries);
+        } catch (IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/Main.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+// The Main Entry point
+package sun.tools.pack.verify;
+
+import java.io.*;
+
+/**
+ * This class provides a convenient entry point to the pack200 verifier. This
+ * compares two classes, either in path or in an archive.
+ * @see xmlkit.XMLKit
+ * @author ksrini
+ */
+public class Main {
+
+    private static void syntax() {
+        System.out.println("Usage: ");
+        System.out.println("\tREFERENCE_CLASSPATH COMPARED_CLASSPATH [Options]");
+        System.out.println("\tOptions:");
+        System.out.println("\t\t-O check jar ordering");
+        System.out.println("\t\t-C ignore compile attributes (Deprecated, SourceFile, Synthetic, )");
+        System.out.println("\t\t-D ignore debug attributes (LocalVariable, LineNumber)");
+        System.out.println("\t\t-u ignore unknown attributes");
+        System.out.println("\t\t-V turn off class validation");
+        System.out.println("\t\t-c CLASS, compare CLASS only");
+        System.out.println("\t\t-b Compares all entries bitwise only");
+        System.out.println("\t\t-l Directory or Log File Name");
+    }
+
+    /**
+     * main entry point to the class file comparator, which compares semantically
+     * class files in a classpath or an archive.
+     * @param args String array as described below
+     * @throws RuntimeException
+     * <pre>
+     *  Usage:
+     *     ReferenceClasspath SpecimenClaspath [Options]
+     *     Options:
+     *      -O check jar ordering
+     *      -C do not compare compile attributes (Deprecated, SourceFile, Synthetic)
+     *      -D do not compare debug attribute (LocalVariableTable, LineNumberTable)
+     *      -u ignore unknown attributes
+     *      -V turn off class validation
+     *      -c class, compare a single class
+     *      -b compares all entries bitwise (fastest)
+     *      -l directory or log file name
+     * </pre>
+     */
+    public static void main(String args[]) {
+        Globals.getInstance();
+        if (args == null || args.length < 2) {
+            syntax();
+            System.exit(1);
+        }
+        String refJarFileName = null;
+        String cmpJarFileName = null;
+        String specificClass = null;
+        String logDirFileName = null;
+
+        for (int i = 0; i < args.length; i++) {
+            if (i == 0) {
+                refJarFileName = args[0];
+                continue;
+            }
+            if (i == 1) {
+                cmpJarFileName = args[1];
+                continue;
+            }
+
+            if (args[i].startsWith("-O")) {
+                Globals.setCheckJarClassOrdering(true);
+            }
+
+            if (args[i].startsWith("-b")) {
+                Globals.setBitWiseClassCompare(true);
+            }
+
+            if (args[i].startsWith("-C")) {
+                Globals.setIgnoreCompileAttributes(true);
+            }
+
+            if (args[i].startsWith("-D")) {
+                Globals.setIgnoreDebugAttributes(true);
+            }
+
+            if (args[i].startsWith("-V")) {
+                Globals.setValidateClass(false);
+            }
+
+            if (args[i].startsWith("-c")) {
+                i++;
+                specificClass = args[i].trim();
+            }
+
+            if (args[i].startsWith("-u")) {
+                i++;
+                Globals.setIgnoreUnknownAttributes(true);
+            }
+
+            if (args[i].startsWith("-l")) {
+                i++;
+                logDirFileName = args[i].trim();
+            }
+        }
+
+        Globals.openLog(logDirFileName);
+
+        File refJarFile = new File(refJarFileName);
+        File cmpJarFile = new File(cmpJarFileName);
+
+        String f1 = refJarFile.getAbsoluteFile().toString();
+        String f2 = cmpJarFile.getAbsoluteFile().toString();
+
+        System.out.println("LogFile:" + Globals.getLogFileName());
+        System.out.println("Reference JAR:" + f1);
+        System.out.println("Compared  JAR:" + f2);
+
+        Globals.println("LogFile:" + Globals.getLogFileName());
+        Globals.println("Reference JAR:" + f1);
+        Globals.println("Compared  JAR:" + f2);
+
+        Globals.println("Ignore Compile Attributes:" + Globals.ignoreCompileAttributes());
+        Globals.println("Ignore Debug   Attributes:" + Globals.ignoreDebugAttributes());
+        Globals.println("Ignore Unknown Attributes:" + Globals.ignoreUnknownAttributes());
+        Globals.println("Class ordering check:" + Globals.checkJarClassOrdering());
+        Globals.println("Class validation check:" + Globals.validateClass());
+        Globals.println("Bit-wise compare:" + Globals.bitWiseClassCompare());
+        Globals.println("ClassName:" + ((specificClass == null) ? "ALL" : specificClass));
+
+        if (specificClass == null && Globals.bitWiseClassCompare() == true) {
+            JarFileCompare.jarCompare(refJarFileName, cmpJarFileName);
+        } else {
+            try {
+                ClassCompare.compareClass(refJarFileName, cmpJarFileName, specificClass);
+            } catch (Exception e) {
+                Globals.log("Exception " + e);
+                throw new RuntimeException(e);
+            }
+        }
+
+        if (Globals.getErrors() > 0) {
+            System.out.println("FAIL");
+            Globals.println("FAIL");
+            System.exit(Globals.getErrors());
+        }
+
+        System.out.println("PASS");
+        Globals.println("PASS");
+        System.exit(Globals.getErrors());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/VerifyTreeSet.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+package sun.tools.pack.verify;
+
+import java.util.*;
+/*
+ * @author ksrini
+ */
+
+class VerifyTreeSet<K> extends java.util.TreeSet {
+
+    VerifyTreeSet() {
+        super();
+    }
+
+    public VerifyTreeSet(Comparator c) {
+        super(c);
+    }
+
+    public TreeSet<K> diff(TreeSet in) {
+        TreeSet<K> delta = (TreeSet<K>) this.clone();
+        delta.removeAll(in);
+        return delta;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,1003 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
+
+import java.util.*;
+import java.util.jar.*;
+import java.lang.reflect.*;
+import java.io.*;
+import xmlkit.XMLKit.Element;
+
+/*
+ * @author jrose
+ */
+public class ClassReader extends ClassSyntax {
+
+    private static final CommandLineParser CLP = new CommandLineParser(""
+            + "-source:     +> = \n"
+            + "-dest:       +> = \n"
+            + "-encoding:   +> = \n"
+            + "-jcov           $ \n   -nojcov         !-jcov        \n"
+            + "-verbose        $ \n   -noverbose      !-verbose     \n"
+            + "-pretty         $ \n   -nopretty       !-pretty      \n"
+            + "-keepPath       $ \n   -nokeepPath     !-keepPath    \n"
+            + "-keepCP         $ \n   -nokeepCP       !-keepCP      \n"
+            + "-keepBytes      $ \n   -nokeepBytes    !-keepBytes   \n"
+            + "-parseBytes     $ \n   -noparseBytes   !-parseBytes  \n"
+            + "-resolveRefs    $ \n   -noresolveRefs  !-resolveRefs \n"
+            + "-keepOrder      $ \n   -nokeepOrder    !-keepOrder   \n"
+            + "-keepSizes      $ \n   -nokeepSizes    !-keepSizes   \n"
+            + "-continue       $ \n   -nocontinue     !-continue    \n"
+            + "-attrDef        & \n"
+            + "-@         >-@  . \n"
+            + "-              +? \n"
+            + "\n");
+
+    public static void main(String[] ava) throws IOException {
+        ArrayList<String> av = new ArrayList<String>(Arrays.asList(ava));
+        HashMap<String, String> props = new HashMap<String, String>();
+        props.put("-encoding:", "UTF8");  // default
+        props.put("-keepOrder", null);    // CLI default
+        props.put("-pretty", "1");     // CLI default
+        props.put("-continue", "1");     // CLI default
+        CLP.parse(av, props);
+        //System.out.println(props+" ++ "+av);
+        File source = asFile(props.get("-source:"));
+        File dest = asFile(props.get("-dest:"));
+        String encoding = props.get("-encoding:");
+        boolean contError = props.containsKey("-continue");
+        ClassReader options = new ClassReader();
+        options.copyOptionsFrom(props);
+        /*
+        if (dest == null && av.size() > 1) {
+        dest = File.createTempFile("TestOut", ".dir", new File("."));
+        dest.delete();
+        if (!dest.mkdir())
+        throw new RuntimeException("Cannot create "+dest);
+        System.out.println("Writing results to "+dest);
+        }
+         */
+        if (av.isEmpty()) {
+            av.add("doit");  //to enter this loop
+        }
+        boolean readList = false;
+        for (String a : av) {
+            if (readList) {
+                readList = false;
+                InputStream fin;
+                if (a.equals("-")) {
+                    fin = System.in;
+                } else {
+                    fin = new FileInputStream(a);
+                }
+
+                BufferedReader files = makeReader(fin, encoding);
+                for (String file; (file = files.readLine()) != null;) {
+                    doFile(file, source, dest, options, encoding, contError);
+                }
+                if (fin != System.in) {
+                    fin.close();
+                }
+            } else if (a.equals("-@")) {
+                readList = true;
+            } else if (a.startsWith("-")) {
+                throw new RuntimeException("Bad flag argument: " + a);
+            } else if (source.getName().endsWith(".jar")) {
+                doJar(a, source, dest, options, encoding, contError);
+            } else {
+                doFile(a, source, dest, options, encoding, contError);
+            }
+        }
+    }
+
+    private static File asFile(String str) {
+        return (str == null) ? null : new File(str);
+    }
+
+    private static void doFile(String a,
+            File source, File dest,
+            ClassReader options, String encoding,
+            boolean contError) throws IOException {
+        if (!contError) {
+            doFile(a, source, dest, options, encoding);
+        } else {
+            try {
+                doFile(a, source, dest, options, encoding);
+            } catch (Exception ee) {
+                System.out.println("Error processing " + source + ": " + ee);
+            }
+        }
+    }
+
+    private static void doJar(String a, File source, File dest, ClassReader options,
+            String encoding, Boolean contError) throws IOException {
+        try {
+            JarFile jf = new JarFile(source);
+            for (JarEntry je : Collections.list((Enumeration<JarEntry>) jf.entries())) {
+                String name = je.getName();
+                if (!name.endsWith(".class")) {
+                    continue;
+                }
+                doStream(name, jf.getInputStream(je), dest, options, encoding);
+            }
+        } catch (IOException ioe) {
+            if (contError) {
+                System.out.println("Error processing " + source + ": " + ioe);
+            } else {
+                throw ioe;
+            }
+        }
+    }
+
+    private static void doStream(String a, InputStream in, File dest,
+            ClassReader options, String encoding) throws IOException {
+
+        File f = new File(a);
+        ClassReader cr = new ClassReader(options);
+        Element e = cr.readFrom(in);
+
+        OutputStream out;
+        if (dest == null) {
+            //System.out.println(e.prettyString());
+            out = System.out;
+        } else {
+            File outf = new File(dest, f.isAbsolute() ? f.getName() : f.getPath());
+            String outName = outf.getName();
+            File outSubdir = outf.getParentFile();
+            outSubdir.mkdirs();
+            int extPos = outName.lastIndexOf('.');
+            if (extPos > 0) {
+                outf = new File(outSubdir, outName.substring(0, extPos) + ".xml");
+            }
+            out = new FileOutputStream(outf);
+        }
+
+        Writer outw = makeWriter(out, encoding);
+        if (options.pretty || !options.keepOrder) {
+            e.writePrettyTo(outw);
+        } else {
+            e.writeTo(outw);
+        }
+        if (out == System.out) {
+            outw.write("\n");
+            outw.flush();
+        } else {
+            outw.close();
+        }
+    }
+
+    private static void doFile(String a,
+            File source, File dest,
+            ClassReader options, String encoding) throws IOException {
+        File inf = new File(source, a);
+        if (dest != null && options.verbose) {
+            System.out.println("Reading " + inf);
+        }
+
+        BufferedInputStream in = new BufferedInputStream(new FileInputStream(inf));
+
+        doStream(a, in, dest, options, encoding);
+
+    }
+
+    public static BufferedReader makeReader(InputStream in, String encoding) throws IOException {
+        // encoding in DEFAULT, '', UTF8, 8BIT, , or any valid encoding name
+        if (encoding.equals("8BIT")) {
+            encoding = EIGHT_BIT_CHAR_ENCODING;
+        }
+        if (encoding.equals("UTF8")) {
+            encoding = UTF8_ENCODING;
+        }
+        if (encoding.equals("DEFAULT")) {
+            encoding = null;
+        }
+        if (encoding.equals("-")) {
+            encoding = null;
+        }
+        Reader inw;
+        in = new BufferedInputStream(in);  // add buffering
+        if (encoding == null) {
+            inw = new InputStreamReader(in);
+        } else {
+            inw = new InputStreamReader(in, encoding);
+        }
+        return new BufferedReader(inw);  // add buffering
+    }
+
+    public static Writer makeWriter(OutputStream out, String encoding) throws IOException {
+        // encoding in DEFAULT, '', UTF8, 8BIT, , or any valid encoding name
+        if (encoding.equals("8BIT")) {
+            encoding = EIGHT_BIT_CHAR_ENCODING;
+        }
+        if (encoding.equals("UTF8")) {
+            encoding = UTF8_ENCODING;
+        }
+        if (encoding.equals("DEFAULT")) {
+            encoding = null;
+        }
+        if (encoding.equals("-")) {
+            encoding = null;
+        }
+        Writer outw;
+        if (encoding == null) {
+            outw = new OutputStreamWriter(out);
+        } else {
+            outw = new OutputStreamWriter(out, encoding);
+        }
+        return new BufferedWriter(outw);  // add buffering
+    }
+
+    public Element result() {
+        return cfile;
+    }
+    protected InputStream in;
+    protected ByteArrayOutputStream buf = new ByteArrayOutputStream(1024);
+    protected byte cpTag[];
+    protected String cpName[];
+    protected String[] callables;     // varies
+    public static final String REF_PREFIX = "#";
+    // input options
+    public boolean pretty = false;
+    public boolean verbose = false;
+    public boolean keepPath = false;
+    public boolean keepCP = false;
+    public boolean keepBytes = false;
+    public boolean parseBytes = true;
+    public boolean resolveRefs = true;
+    public boolean keepOrder = true;
+    public boolean keepSizes = false;
+
+    public ClassReader() {
+        super.cfile = new Element("ClassFile");
+    }
+
+    public ClassReader(ClassReader options) {
+        this();
+        copyOptionsFrom(options);
+    }
+
+    public void copyOptionsFrom(ClassReader options) {
+        pretty = options.pretty;
+        verbose = options.verbose;
+        keepPath = options.keepPath;
+        keepCP = options.keepCP;
+        keepBytes = options.keepBytes;
+        parseBytes = options.parseBytes;
+        resolveRefs = options.resolveRefs;
+        keepSizes = options.keepSizes;
+        keepOrder = options.keepOrder;
+        attrTypes = options.attrTypes;
+    }
+
+    public void copyOptionsFrom(Map<String, String> options) {
+        if (options.containsKey("-pretty")) {
+            pretty = (options.get("-pretty") != null);
+        }
+        if (options.containsKey("-verbose")) {
+            verbose = (options.get("-verbose") != null);
+        }
+        if (options.containsKey("-keepPath")) {
+            keepPath = (options.get("-keepPath") != null);
+        }
+        if (options.containsKey("-keepCP")) {
+            keepCP = (options.get("-keepCP") != null);
+        }
+        if (options.containsKey("-keepBytes")) {
+            keepBytes = (options.get("-keepBytes") != null);
+        }
+        if (options.containsKey("-parseBytes")) {
+            parseBytes = (options.get("-parseBytes") != null);
+        }
+        if (options.containsKey("-resolveRefs")) {
+            resolveRefs = (options.get("-resolveRefs") != null);
+        }
+        if (options.containsKey("-keepSizes")) {
+            keepSizes = (options.get("-keepSizes") != null);
+        }
+        if (options.containsKey("-keepOrder")) {
+            keepOrder = (options.get("-keepOrder") != null);
+        }
+        if (options.containsKey("-attrDef")) {
+            addAttrTypes(options.get("-attrDef").split(" "));
+        }
+        if (options.get("-jcov") != null) {
+            addJcovAttrTypes();
+        }
+    }
+
+    public Element readFrom(InputStream in) throws IOException {
+        this.in = in;
+        // read the file header
+        int magic = u4();
+        if (magic != 0xCAFEBABE) {
+            throw new RuntimeException("bad magic number " + Integer.toHexString(magic));
+        }
+        cfile.setAttr("magic", "" + magic);
+        int minver = u2();
+        int majver = u2();
+        cfile.setAttr("minver", "" + minver);
+        cfile.setAttr("majver", "" + majver);
+        readCP();
+        readClass();
+        return result();
+    }
+
+    public Element readFrom(File file) throws IOException {
+        InputStream in = null;
+        try {
+            in = new FileInputStream(file);
+            Element e = readFrom(new BufferedInputStream(in));
+            if (keepPath) {
+                e.setAttr("path", file.toString());
+            }
+            return e;
+        } finally {
+            if (in != null) {
+                in.close();
+            }
+        }
+    }
+
+    private void readClass() throws IOException {
+        klass = new Element("Class");
+        cfile.add(klass);
+        int flags = u2();
+        String thisk = cpRef();
+        String superk = cpRef();
+        klass.setAttr("name", thisk);
+        boolean flagsSync = ((flags & Modifier.SYNCHRONIZED) != 0);
+        flags &= ~Modifier.SYNCHRONIZED;
+        String flagString = flagString(flags, klass);
+        if (!flagsSync) {
+            if (flagString.length() > 0) {
+                flagString += " ";
+            }
+            flagString += "!synchronized";
+        }
+        klass.setAttr("flags", flagString);
+        klass.setAttr("super", superk);
+        for (int len = u2(), i = 0; i < len; i++) {
+            String interk = cpRef();
+            klass.add(new Element("Interface", "name", interk));
+        }
+        Element fields = readMembers("Field");
+        klass.addAll(fields);
+        Element methods = readMembers("Method");
+        if (!keepOrder) {
+            methods.sort();
+        }
+        klass.addAll(methods);
+        readAttributesFor(klass);
+        klass.trimToSize();
+        if (keepSizes) {
+            attachTo(cfile, formatAttrSizes());
+        }
+        if (paddingSize != 0) {
+            cfile.setAttr("padding", "" + paddingSize);
+        }
+    }
+
+    private Element readMembers(String kind) throws IOException {
+        int len = u2();
+        Element members = new Element(len);
+        for (int i = 0; i < len; i++) {
+            Element member = new Element(kind);
+            int flags = u2();
+            String name = cpRef();
+            String type = cpRef();
+            member.setAttr("name", name);
+            member.setAttr("type", type);
+            member.setAttr("flags", flagString(flags, member));
+            readAttributesFor(member);
+            member.trimToSize();
+            members.add(member);
+        }
+        return members;
+    }
+
+    protected String flagString(int flags, Element holder) {
+        // Superset of Modifier.toString.
+        int kind = 0;
+        if (holder.getName() == "Field") {
+            kind = 1;
+        }
+        if (holder.getName() == "Method") {
+            kind = 2;
+        }
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; flags != 0; i++, flags >>>= 1) {
+            if ((flags & 1) != 0) {
+                if (sb.length() > 0) {
+                    sb.append(' ');
+                }
+                if (i < modifierNames.length) {
+                    String[] names = modifierNames[i];
+                    String name = (kind < names.length) ? names[kind] : null;
+                    for (String name2 : names) {
+                        if (name != null) {
+                            break;
+                        }
+                        name = name2;
+                    }
+                    sb.append(name);
+                } else {
+                    sb.append("#").append(1 << i);
+                }
+            }
+        }
+        return sb.toString();
+    }
+
+    private void readAttributesFor(Element x) throws IOException {
+        Element prevCurrent;
+        Element y = new Element();
+        if (x.getName() == "Code") {
+            prevCurrent = currentCode;
+            currentCode = x;
+        } else {
+            prevCurrent = currentMember;
+            currentMember = x;
+        }
+        for (int len = u2(), i = 0; i < len; i++) {
+            int ref = u2();
+            String uname = cpName(ref).intern();
+            String refName = uname;
+            if (!resolveRefs) {
+                refName = (REF_PREFIX + ref).intern();
+            }
+            String qname = (x.getName() + "." + uname).intern();
+            String wname = ("*." + uname).intern();
+            String type = attrTypes.get(qname);
+            if (type == null || "".equals(type)) {
+                type = attrTypes.get(wname);
+            }
+            if ("".equals(type)) {
+                type = null;
+            }
+            int size = u4();
+            int[] countVar = attrSizes.get(qname);
+            if (countVar == null) {
+                attrSizes.put(qname, countVar = new int[2]);
+            }
+            countVar[0] += 1;
+            countVar[1] += size;
+            buf.reset();
+            for (int j = 0; j < size; j++) {
+                buf.write(u1());
+            }
+            if (type == null && size == 0) {
+                y.add(new Element(uname)); // <Bridge>, etc.
+            } else if (type == null) {
+                //System.out.println("Warning:  No attribute type description: "+qname);
+                // write cdata attribute
+                Element a = new Element("Attribute",
+                        new String[]{"Name", refName},
+                        buf.toString(EIGHT_BIT_CHAR_ENCODING));
+                a.addContent(getCPDigest());
+                y.add(a);
+            } else if (type.equals("")) {
+                // ignore this attribute...
+            } else {
+                InputStream in0 = in;
+                int fileSize0 = fileSize;
+                ByteArrayInputStream in1 = new ByteArrayInputStream(buf.toByteArray());
+                boolean ok = false;
+                try {
+                    in = in1;
+                    // parse according to type desc.
+                    Element aval;
+                    if (type.equals("<Code>...")) {
+                        // delve into Code attribute
+                        aval = readCode();
+                    } else if (type.equals("<Frame>...")) {
+                        // delve into StackMap attribute
+                        aval = readStackMap(false);
+                    } else if (type.equals("<FrameX>...")) {
+                        // delve into StackMap attribute
+                        aval = readStackMap(true);
+                    } else if (type.startsWith("[")) {
+                        aval = readAttributeCallables(type);
+                    } else {
+                        aval = readAttribute(type);
+                    }
+                    //System.out.println("attachTo 1 "+y+" <- "+aval);
+                    attachTo(y, aval);
+                    if (false
+                            && in1.available() != 0) {
+                        throw new RuntimeException("extra bytes in " + qname + " :" + in1.available());
+                    }
+                    ok = true;
+                } finally {
+                    in = in0;
+                    fileSize = fileSize0;
+                    if (!ok) {
+                        System.out.println("*** Failed to read " + type);
+                    }
+                }
+            }
+        }
+        if (x.getName() == "Code") {
+            currentCode = prevCurrent;
+        } else {
+            currentMember = prevCurrent;
+        }
+        if (!keepOrder) {
+            y.sort();
+            y.sortAttrs();
+        }
+        //System.out.println("attachTo 2 "+x+" <- "+y);
+        attachTo(x, y);
+    }
+    private int fileSize = 0;
+    private int paddingSize = 0;
+    private HashMap<String, int[]> attrSizes = new HashMap<String, int[]>();
+
+    private Element formatAttrSizes() {
+        Element e = new Element("Sizes");
+        e.setAttr("fileSize", "" + fileSize);
+        for (Map.Entry<String, int[]> ie : attrSizes.entrySet()) {
+            int[] countVar = ie.getValue();
+            e.add(new Element("AttrSize",
+                    "name", ie.getKey().toString(),
+                    "count", "" + countVar[0],
+                    "size", "" + countVar[1]));
+        }
+        return e;
+    }
+
+    private void attachTo(Element x, Object aval0) {
+        if (aval0 == null) {
+            return;
+        }
+        //System.out.println("attachTo "+x+" : "+aval0);
+        if (!(aval0 instanceof Element)) {
+            x.add(aval0);
+            return;
+        }
+        Element aval = (Element) aval0;
+        if (!aval.isAnonymous()) {
+            x.add(aval);
+            return;
+        }
+        for (int imax = aval.attrSize(), i = 0; i < imax; i++) {
+            //%%
+            attachAttrTo(x, aval.getAttrName(i), aval.getAttr(i));
+        }
+        x.addAll(aval);
+    }
+
+    private void attachAttrTo(Element x, String aname, String aval) {
+        //System.out.println("attachAttrTo "+x+" : "+aname+"="+aval);
+        String aval0 = x.getAttr(aname);
+        if (aval0 != null) {
+            aval = aval0 + " " + aval;
+        }
+        x.setAttr(aname, aval);
+    }
+
+    private Element readAttributeCallables(String type) throws IOException {
+        assert (callables == null);
+        callables = getBodies(type);
+        Element res = readAttribute(callables[0]);
+        callables = null;
+        return res;
+    }
+
+    private Element readAttribute(String type) throws IOException {
+        //System.out.println("readAttribute "+type);
+        Element aval = new Element();
+        String nextAttrName = null;
+        for (int len = type.length(), next, i = 0; i < len; i = next) {
+            String value;
+            switch (type.charAt(i)) {
+                case '<':
+                    assert (nextAttrName == null);
+                    next = type.indexOf('>', ++i);
+                    String form = type.substring(i, next++);
+                    if (form.indexOf('=') < 0) {
+                        //  elem_placement = '<' elemname '>'
+                        assert (aval.attrSize() == 0);
+                        assert (aval.isAnonymous());
+                        aval.setName(form.intern());
+                    } else {
+                        //  attr_placement = '<' attrname '=' (value)? '>'
+                        int eqPos = form.indexOf('=');
+                        nextAttrName = form.substring(0, eqPos).intern();
+                        if (eqPos != form.length() - 1) {
+                            value = form.substring(eqPos + 1);
+                            attachAttrTo(aval, nextAttrName, value);
+                            nextAttrName = null;
+                        }
+                        // ...else subsequent type parsing will find the attr value
+                        // and add it as "nextAttrName".
+                    }
+                    continue;
+                case '(':
+                    next = type.indexOf(')', ++i);
+                    int callee = Integer.parseInt(type.substring(i, next++));
+                    attachTo(aval, readAttribute(callables[callee]));
+                    continue;
+                case 'N': // replication = 'N' int '[' type ... ']'
+                {
+                    int count = getInt(type.charAt(i + 1), false);
+                    assert (count >= 0);
+                    next = i + 2;
+                    String type1 = getBody(type, next);
+                    next += type1.length() + 2;  // skip body and brackets
+                    for (int j = 0; j < count; j++) {
+                        attachTo(aval, readAttribute(type1));
+                    }
+                }
+                continue;
+                case 'T': // union = 'T' any_int union_case* '(' ')' '[' body ']'
+                    int tagValue;
+                    if (type.charAt(++i) == 'S') {
+                        tagValue = getInt(type.charAt(++i), true);
+                    } else {
+                        tagValue = getInt(type.charAt(i), false);
+                    }
+                    attachAttrTo(aval, "tag", "" + tagValue);  // always named "tag"
+                    ++i;  // skip the int type char
+                    // union_case = '(' uc_tag (',' uc_tag)* ')' '[' body ']'
+                    // uc_tag = ('-')? digit+
+                    for (boolean foundCase = false;; i = next) {
+                        assert (type.charAt(i) == '(');
+                        next = type.indexOf(')', ++i);
+                        assert (next >= i);
+                        if (type.charAt(next - 1) == '\\'
+                                && type.charAt(next - 2) != '\\') // Skip an escaped paren.
+                        {
+                            next = type.indexOf(')', next + 1);
+                        }
+                        String caseStr = type.substring(i, next++);
+                        String type1 = getBody(type, next);
+                        next += type1.length() + 2;  // skip body and brackets
+                        boolean lastCase = (caseStr.length() == 0);
+                        if (!foundCase
+                                && (lastCase || matchTag(tagValue, caseStr))) {
+                            foundCase = true;
+                            // Execute this body.
+                            attachTo(aval, readAttribute(type1));
+                        }
+                        if (lastCase) {
+                            break;
+                        }
+                    }
+                    continue;
+                case 'B':
+                case 'H':
+                case 'I': // int = oneof "BHI"
+                    next = i + 1;
+                    value = "" + getInt(type.charAt(i), false);
+                    break;
+                case 'K':
+                    assert ("IJFDLQ".indexOf(type.charAt(i + 1)) >= 0);
+                    assert (type.charAt(i + 2) == 'H');  // only H works for now
+                    next = i + 3;
+                    value = cpRef();
+                    break;
+                case 'R':
+                    assert ("CSDFMIU?".indexOf(type.charAt(i + 1)) >= 0);
+                    assert (type.charAt(i + 2) == 'H');  // only H works for now
+                    next = i + 3;
+                    value = cpRef();
+                    break;
+                case 'P':  // bci = 'P' int
+                    next = i + 2;
+                    value = "" + getInt(type.charAt(i + 1), false);
+                    break;
+                case 'S':  // signed_int = 'S' int
+                    next = i + 2;
+                    value = "" + getInt(type.charAt(i + 1), true);
+                    break;
+                case 'F':
+                    next = i + 2;
+                    value = flagString(getInt(type.charAt(i + 1), false), currentMember);
+                    break;
+                default:
+                    throw new RuntimeException("bad attr format '" + type.charAt(i) + "': " + type);
+            }
+            // store the value
+            if (nextAttrName != null) {
+                attachAttrTo(aval, nextAttrName, value);
+                nextAttrName = null;
+            } else {
+                attachTo(aval, value);
+            }
+        }
+        //System.out.println("readAttribute => "+aval);
+        assert (nextAttrName == null);
+        return aval;
+    }
+
+    private int getInt(char ch, boolean signed) throws IOException {
+        if (signed) {
+            switch (ch) {
+                case 'B':
+                    return (byte) u1();
+                case 'H':
+                    return (short) u2();
+                case 'I':
+                    return (int) u4();
+            }
+        } else {
+            switch (ch) {
+                case 'B':
+                    return u1();
+                case 'H':
+                    return u2();
+                case 'I':
+                    return u4();
+            }
+        }
+        assert ("BHIJ".indexOf(ch) >= 0);
+        return 0;
+    }
+
+    private Element readCode() throws IOException {
+        int stack = u2();
+        int local = u2();
+        int length = u4();
+        StringBuilder sb = new StringBuilder(length);
+        for (int i = 0; i < length; i++) {
+            sb.append((char) u1());
+        }
+        String bytecodes = sb.toString();
+        Element e = new Element("Code",
+                "stack", "" + stack,
+                "local", "" + local);
+        Element bytes = new Element("Bytes", (String[]) null, bytecodes);
+        if (keepBytes) {
+            e.add(bytes);
+        }
+        if (parseBytes) {
+            e.add(parseByteCodes(bytecodes));
+        }
+        for (int len = u2(), i = 0; i < len; i++) {
+            int start = u2();
+            int end = u2();
+            int catsh = u2();
+            String clasz = cpRef();
+            e.add(new Element("Handler",
+                    "start", "" + start,
+                    "end", "" + end,
+                    "catch", "" + catsh,
+                    "class", clasz));
+        }
+        readAttributesFor(e);
+        e.trimToSize();
+        return e;
+    }
+
+    private Element parseByteCodes(String bytecodes) {
+        Element e = InstructionSyntax.parse(bytecodes);
+        for (Element ins : e.elements()) {
+            Number ref = ins.getAttrNumber("ref");
+            if (ref != null && resolveRefs) {
+                int id = ref.intValue();
+                String val = cpName(id);
+                if (ins.getName().startsWith("ldc")) {
+                    // Yuck:  Arb. string cannot be an XML attribute.
+                    ins.add(val);
+                    val = "";
+                    byte tag = (id >= 0 && id < cpTag.length) ? cpTag[id] : 0;
+                    if (tag != 0) {
+                        ins.setAttrLong("tag", tag);
+                    }
+                }
+                if (ins.getName() == "invokeinterface"
+                        && computeInterfaceNum(val) == ins.getAttrLong("num")) {
+                    ins.setAttr("num", null);  // garbage bytes
+                }
+                ins.setAttr("ref", null);
+                ins.setAttr("val", val);
+            }
+        }
+        return e;
+    }
+
+    private Element readStackMap(boolean hasXOption) throws IOException {
+        Element result = new Element();
+        Element bytes = currentCode.findElement("Bytes");
+        assert (bytes != null && bytes.size() == 1);
+        int byteLength = ((String) bytes.get(0)).length();
+        boolean uoffsetIsU4 = (byteLength >= (1 << 16));
+        boolean ulocalvarIsU4 = currentCode.getAttrLong("local") >= (1 << 16);
+        boolean ustackIsU4 = currentCode.getAttrLong("stack") >= (1 << 16);
+        if (hasXOption || uoffsetIsU4 || ulocalvarIsU4 || ustackIsU4) {
+            Element flags = new Element("StackMapFlags");
+            if (hasXOption) {
+                flags.setAttr("hasXOption", "true");
+            }
+            if (uoffsetIsU4) {
+                flags.setAttr("uoffsetIsU4", "true");
+            }
+            if (ulocalvarIsU4) {
+                flags.setAttr("ulocalvarIsU4", "true");
+            }
+            if (ustackIsU4) {
+                flags.setAttr("ustackIsU4", "true");
+            }
+            currentCode.add(flags);
+        }
+        int frame_count = (uoffsetIsU4 ? u4() : u2());
+        for (int i = 0; i < frame_count; i++) {
+            int bci = (uoffsetIsU4 ? u4() : u2());
+            int flags = (hasXOption ? u1() : 0);
+            Element frame = new Element("Frame");
+            result.add(frame);
+            if (flags != 0) {
+                frame.setAttr("flags", "" + flags);
+            }
+            frame.setAttr("bci", "" + bci);
+            // Scan local and stack types in this frame:
+            final int LOCALS = 0, STACK = 1;
+            for (int j = LOCALS; j <= STACK; j++) {
+                int typeSize;
+                if (j == LOCALS) {
+                    typeSize = (ulocalvarIsU4 ? u4() : u2());
+                } else { // STACK
+                    typeSize = (ustackIsU4 ? u4() : u2());
+                }
+                Element types = new Element(j == LOCALS ? "Local" : "Stack");
+                for (int k = 0; k < typeSize; k++) {
+                    int tag = u1();
+                    Element type = new Element(itemTagName(tag));
+                    types.add(type);
+                    switch (tag) {
+                        case ITEM_Object:
+                            type.setAttr("class", cpRef());
+                            break;
+                        case ITEM_Uninitialized:
+                        case ITEM_ReturnAddress:
+                            type.setAttr("bci", "" + (uoffsetIsU4 ? u4() : u2()));
+                            break;
+                    }
+                }
+                if (types.size() > 0) {
+                    frame.add(types);
+                }
+            }
+        }
+        return result;
+    }
+
+    private void readCP() throws IOException {
+        int cpLen = u2();
+        cpTag = new byte[cpLen];
+        cpName = new String[cpLen];
+        int cpTem[][] = new int[cpLen][];
+        for (int i = 1; i < cpLen; i++) {
+            cpTag[i] = (byte) u1();
+            switch (cpTag[i]) {
+                case CONSTANT_Utf8:
+                    buf.reset();
+                    for (int len = u2(), j = 0; j < len; j++) {
+                        buf.write(u1());
+                    }
+                    cpName[i] = buf.toString(UTF8_ENCODING);
+                    break;
+                case CONSTANT_Integer:
+                    cpName[i] = String.valueOf((int) u4());
+                    break;
+                case CONSTANT_Float:
+                    cpName[i] = String.valueOf(Float.intBitsToFloat(u4()));
+                    break;
+                case CONSTANT_Long:
+                    cpName[i] = String.valueOf(u8());
+                    i += 1;
+                    break;
+                case CONSTANT_Double:
+                    cpName[i] = String.valueOf(Double.longBitsToDouble(u8()));
+                    i += 1;
+                    break;
+                case CONSTANT_Class:
+                case CONSTANT_String:
+                    cpTem[i] = new int[]{u2()};
+                    break;
+                case CONSTANT_Fieldref:
+                case CONSTANT_Methodref:
+                case CONSTANT_InterfaceMethodref:
+                case CONSTANT_NameAndType:
+                    cpTem[i] = new int[]{u2(), u2()};
+                    break;
+            }
+        }
+        for (int i = 1; i < cpLen; i++) {
+            switch (cpTag[i]) {
+                case CONSTANT_Class:
+                case CONSTANT_String:
+                    cpName[i] = cpName[cpTem[i][0]];
+                    break;
+                case CONSTANT_NameAndType:
+                    cpName[i] = cpName[cpTem[i][0]] + " " + cpName[cpTem[i][1]];
+                    break;
+            }
+        }
+        // do fieldref et al after nameandtype are all resolved
+        for (int i = 1; i < cpLen; i++) {
+            switch (cpTag[i]) {
+                case CONSTANT_Fieldref:
+                case CONSTANT_Methodref:
+                case CONSTANT_InterfaceMethodref:
+                    cpName[i] = cpName[cpTem[i][0]] + " " + cpName[cpTem[i][1]];
+                    break;
+            }
+        }
+        cpool = new Element("ConstantPool", cpName.length);
+        for (int i = 0; i < cpName.length; i++) {
+            if (cpName[i] == null) {
+                continue;
+            }
+            cpool.add(new Element(cpTagName(cpTag[i]),
+                    new String[]{"id", "" + i},
+                    cpName[i]));
+        }
+        if (keepCP) {
+            cfile.add(cpool);
+        }
+    }
+
+    private String cpRef() throws IOException {
+        int ref = u2();
+        if (resolveRefs) {
+            return cpName(ref);
+        } else {
+            return REF_PREFIX + ref;
+        }
+    }
+
+    private String cpName(int id) {
+        if (id >= 0 && id < cpName.length) {
+            return cpName[id];
+        } else {
+            return "[CP#" + Integer.toHexString(id) + "]";
+        }
+    }
+
+    private long u8() throws IOException {
+        return ((long) u4() << 32) + (((long) u4() << 32) >>> 32);
+    }
+
+    private int u4() throws IOException {
+        return (u2() << 16) + u2();
+    }
+
+    private int u2() throws IOException {
+        return (u1() << 8) + u1();
+    }
+
+    private int u1() throws IOException {
+        int x = in.read();
+        if (x < 0) {
+            paddingSize++;
+            return 0;  // error recovery
+        }
+        fileSize++;
+        assert (x == (x & 0xFF));
+        return x;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/pack200-verifier/src/xmlkit/ClassSyntax.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,518 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
+import xmlkit.XMLKit.*;
+
+import java.util.*;
+import java.security.MessageDigest;
+import java.nio.ByteBuffer;
+import xmlkit.XMLKit.Element;
+/*
+ * @author jrose
+ */
+public abstract class ClassSyntax {
+
+    public interface GetCPIndex {
+
+        int getCPIndex(int tag, String name);  // cp finder
+    }
+    public static final int CONSTANT_Utf8 = 1,
+            CONSTANT_Integer = 3,
+            CONSTANT_Float = 4,
+            CONSTANT_Long = 5,
+            CONSTANT_Double = 6,
+            CONSTANT_Class = 7,
+            CONSTANT_String = 8,
+            CONSTANT_Fieldref = 9,
+            CONSTANT_Methodref = 10,
+            CONSTANT_InterfaceMethodref = 11,
+            CONSTANT_NameAndType = 12;
+    private static final String[] cpTagName = {
+        /* 0:  */null,
+        /* 1:  */ "Utf8",
+        /* 2:  */ null,
+        /* 3:  */ "Integer",
+        /* 4:  */ "Float",
+        /* 5:  */ "Long",
+        /* 6:  */ "Double",
+        /* 7:  */ "Class",
+        /* 8:  */ "String",
+        /* 9:  */ "Fieldref",
+        /* 10: */ "Methodref",
+        /* 11: */ "InterfaceMethodref",
+        /* 12: */ "NameAndType",
+        null
+    };
+    private static final Set<String> cpTagNames;
+
+    static {
+        Set<String> set = new HashSet<String>(Arrays.asList(cpTagName));
+        set.remove(null);
+        cpTagNames = Collections.unmodifiableSet(set);
+    }
+    public static final int ITEM_Top = 0, // replicates by [1..4,1..4]
+            ITEM_Integer = 1, // (ditto)
+            ITEM_Float = 2,
+            ITEM_Double = 3,
+            ITEM_Long = 4,
+            ITEM_Null = 5,
+            ITEM_UninitializedThis = 6,
+            ITEM_Object = 7,
+            ITEM_Uninitialized = 8,
+            ITEM_ReturnAddress = 9,
+            ITEM_LIMIT = 10;
+    private static final String[] itemTagName = {
+        "Top",
+        "Integer",
+        "Float",
+        "Double",
+        "Long",
+        "Null",
+        "UninitializedThis",
+        "Object",
+        "Uninitialized",
+        "ReturnAddress",};
+    private static final Set<String> itemTagNames;
+
+    static {
+        Set<String> set = new HashSet<String>(Arrays.asList(itemTagName));
+        set.remove(null);
+        itemTagNames = Collections.unmodifiableSet(set);
+    }
+    protected static final HashMap<String, String> attrTypesBacking;
+    protected static final Map<String, String> attrTypesInit;
+
+    static {
+        HashMap<String, String> at = new HashMap<String, String>();
+
+        //at.put("*.Deprecated", "<deprecated=true>");
+        //at.put("*.Synthetic", "<synthetic=true>");
+        ////at.put("Field.ConstantValue", "<constantValue=>KQH");
+        //at.put("Class.SourceFile", "<sourceFile=>RUH");
+        at.put("Method.Bridge", "<Bridge>");
+        at.put("Method.Varargs", "<Varargs>");
+        at.put("Class.Enum", "<Enum>");
+        at.put("*.Signature", "<Signature>RSH");
+        //at.put("*.Deprecated", "<Deprecated>");
+        //at.put("*.Synthetic", "<Synthetic>");
+        at.put("Field.ConstantValue", "<ConstantValue>KQH");
+        at.put("Class.SourceFile", "<SourceFile>RUH");
+        at.put("Class.InnerClasses", "NH[<InnerClass><class=>RCH<outer=>RCH<name=>RUH<flags=>FH]");
+        at.put("Code.LineNumberTable", "NH[<LineNumber><bci=>PH<line=>H]");
+        at.put("Code.LocalVariableTable", "NH[<LocalVariable><bci=>PH<span=>H<name=>RUH<type=>RSH<slot=>H]");
+        at.put("Code.LocalVariableTypeTable", "NH[<LocalVariableType><bci=>PH<span=>H<name=>RUH<type=>RSH<slot=>H]");
+        at.put("Method.Exceptions", "NH[<Exception><name=>RCH]");
+        at.put("Method.Code", "<Code>...");
+        at.put("Code.StackMapTable", "<Frame>...");
+        //at.put("Code.StkMapX", "<FrameX>...");
+        if (true) {
+            at.put("Code.StackMapTable",
+                    "[NH[<Frame>(1)]]"
+                    + "[TB"
+                    + "(64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79"
+                    + ",80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95"
+                    + ",96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111"
+                    + ",112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127"
+                    + ")[<SameLocals1StackItemFrame>(4)]"
+                    + "(247)[<SameLocals1StackItemExtended>H(4)]"
+                    + "(248)[<Chop3>H]"
+                    + "(249)[<Chop2>H]"
+                    + "(250)[<Chop1>H]"
+                    + "(251)[<SameFrameExtended>H]"
+                    + "(252)[<Append1>H(4)]"
+                    + "(253)[<Append2>H(4)(4)]"
+                    + "(254)[<Append3>H(4)(4)(4)]"
+                    + "(255)[<FullFrame>H(2)(3)]"
+                    + "()[<SameFrame>]]"
+                    + "[NH[<Local>(4)]]"
+                    + "[NH[<Stack>(4)]]"
+                    + "[TB"
+                    + ("(0)[<Top>]"
+                    + "(1)[<ItemInteger>](2)[<ItemFloat>](3)[<ItemDouble>](4)[<ItemLong>]"
+                    + "(5)[<ItemNull>](6)[<ItemUninitializedThis>]"
+                    + "(7)[<ItemObject><class=>RCH]"
+                    + "(8)[<ItemUninitialized><bci=>PH]"
+                    + "()[<ItemUnknown>]]"));
+        }
+
+        at.put("Class.EnclosingMethod", "<EnclosingMethod><class=>RCH<desc=>RDH");//RDNH
+
+        // Layouts of metadata attrs:
+        String vpf = "[<RuntimeVisibleAnnotation>";
+        String ipf = "[<RuntimeInvisibleAnnotation>";
+        String apf = "[<Annotation>";
+        String mdanno2 = ""
+                + "<type=>RSHNH[<Member><name=>RUH(3)]]"
+                + ("[TB"
+                + "(\\B,\\C,\\I,\\S,\\Z)[<value=>KIH]"
+                + "(\\D)[<value=>KDH]"
+                + "(\\F)[<value=>KFH]"
+                + "(\\J)[<value=>KJH]"
+                + "(\\c)[<class=>RSH]"
+                + "(\\e)[<type=>RSH<name=>RUH]"
+                + "(\\s)[<String>RUH]"
+                + "(\\@)[(2)]"
+                + "(\\[)[NH[<Element>(3)]]"
+                + "()[]"
+                + "]");
+        String visanno = "[NH[(2)]][(1)]" + vpf + mdanno2;
+        String invanno = "[NH[(2)]][(1)]" + ipf + mdanno2;
+        String vparamanno = ""
+                + "[NB[<RuntimeVisibleParameterAnnotation>(1)]][NH[(2)]]"
+                + apf + mdanno2;
+        String iparamanno = ""
+                + "[NB[<RuntimeInvisibleParameterAnnotation>(1)]][NH[(2)]]"
+                + apf + mdanno2;
+        String mdannodef = "[<AnnotationDefault>(3)][(1)]" + apf + mdanno2;
+        String[] mdplaces = {"Class", "Field", "Method"};
+        for (String place : mdplaces) {
+            at.put(place + ".RuntimeVisibleAnnotations", visanno);
+            at.put(place + ".RuntimeInvisibleAnnotations", invanno);
+        }
+        at.put("Method.RuntimeVisibleParameterAnnotations", vparamanno);
+        at.put("Method.RuntimeInvisibleParameterAnnotations", iparamanno);
+        at.put("Method.AnnotationDefault", mdannodef);
+
+        attrTypesBacking = at;
+        attrTypesInit = Collections.unmodifiableMap(at);
+    }
+
+    ;
+    private static final String[] jcovAttrTypes = {
+        "Code.CoverageTable=NH[<Coverage><bci=>PH<type=>H<line=>I<pos=>I]",
+        "Code.CharacterRangeTable=NH[<CharacterRange><bci=>PH<endbci=>POH<from=>I<to=>I<flag=>H]",
+        "Class.SourceID=<SourceID><id=>RUH",
+        "Class.CompilationID=<CompilationID><id=>RUH"
+    };
+    protected static final String[][] modifierNames = {
+        {"public"},
+        {"private"},
+        {"protected"},
+        {"static"},
+        {"final"},
+        {"synchronized"},
+        {null, "volatile", "bridge"},
+        {null, "transient", "varargs"},
+        {null, null, "native"},
+        {"interface"},
+        {"abstract"},
+        {"strictfp"},
+        {"synthetic"},
+        {"annotation"},
+        {"enum"},};
+    protected static final String EIGHT_BIT_CHAR_ENCODING = "ISO8859_1";
+    protected static final String UTF8_ENCODING = "UTF8";
+    // What XML tags are used by this syntax, apart from attributes?
+    protected static final Set<String> nonAttrTags;
+
+    static {
+        HashSet<String> tagSet = new HashSet<String>();
+        Collections.addAll(tagSet, new String[]{
+                    "ConstantPool",// the CP
+                    "Class", // the class
+                    "Interface", // implemented interfaces
+                    "Method", // methods
+                    "Field", // fields
+                    "Handler", // exception handler pseudo-attribute
+                    "Attribute", // unparsed attribute
+                    "Bytes", // bytecodes
+                    "Instructions" // bytecodes, parsed
+                });
+        nonAttrTags = Collections.unmodifiableSet(tagSet);
+    }
+
+    // Accessors.
+    public static Set<String> nonAttrTags() {
+        return nonAttrTags;
+    }
+
+    public static String cpTagName(int t) {
+        t &= 0xFF;
+        String ts = null;
+        if (t < cpTagName.length) {
+            ts = cpTagName[t];
+        }
+        if (ts != null) {
+            return ts;
+        }
+        return ("UnknownTag" + (int) t).intern();
+    }
+
+    public static int cpTagValue(String name) {
+        for (int t = 0; t < cpTagName.length; t++) {
+            if (name.equals(cpTagName[t])) {
+                return t;
+            }
+        }
+        return 0;
+    }
+
+    public static String itemTagName(int t) {
+        t &= 0xFF;
+        String ts = null;
+        if (t < itemTagName.length) {
+            ts = itemTagName[t];
+        }
+        if (ts != null) {
+            return ts;
+        }
+        return ("UnknownItem" + (int) t).intern();
+    }
+
+    public static int itemTagValue(String name) {
+        for (int t = 0; t < itemTagName.length; t++) {
+            if (name.equals(itemTagName[t])) {
+                return t;
+            }
+        }
+        return -1;
+    }
+
+    public void addJcovAttrTypes() {
+        addAttrTypes(jcovAttrTypes);
+    }
+    // Public methods for declaring attribute types.
+    protected Map<String, String> attrTypes = attrTypesInit;
+
+    public void addAttrType(String opt) {
+        int eqpos = opt.indexOf('=');
+        addAttrType(opt.substring(0, eqpos), opt.substring(eqpos + 1));
+    }
+
+    public void addAttrTypes(String[] opts) {
+        for (String opt : opts) {
+            addAttrType(opt);
+        }
+    }
+
+    private void checkAttr(String attr) {
+        if (!attr.startsWith("Class.")
+                && !attr.startsWith("Field.")
+                && !attr.startsWith("Method.")
+                && !attr.startsWith("Code.")
+                && !attr.startsWith("*.")) {
+            throw new IllegalArgumentException("attr name must start with 'Class.', etc.");
+        }
+        String uattr = attr.substring(attr.indexOf('.') + 1);
+        if (nonAttrTags.contains(uattr)) {
+            throw new IllegalArgumentException("attr name must not be one of " + nonAttrTags);
+        }
+    }
+
+    private void checkAttrs(Map<String, String> at) {
+        for (String attr : at.keySet()) {
+            checkAttr(attr);
+        }
+    }
+
+    private void modAttrs() {
+        if (attrTypes == attrTypesInit) {
+            // Make modifiable.
+            attrTypes = new HashMap<String, String>(attrTypesBacking);
+        }
+    }
+
+    public void addAttrType(String attr, String fmt) {
+        checkAttr(attr);
+        modAttrs();
+        attrTypes.put(attr, fmt);
+    }
+
+    public void addAttrTypes(Map<String, String> at) {
+        checkAttrs(at);
+        modAttrs();
+        attrTypes.putAll(at);
+    }
+
+    public Map<String, String> getAttrTypes() {
+        if (attrTypes == attrTypesInit) {
+            return attrTypes;
+        }
+        return Collections.unmodifiableMap(attrTypes);
+    }
+
+    public void setAttrTypes(Map<String, String> at) {
+        checkAttrs(at);
+        modAttrs();
+        attrTypes.keySet().retainAll(at.keySet());
+        attrTypes.putAll(at);
+    }
+
+    // attr format helpers
+    protected static boolean matchTag(int tagValue, String caseStr) {
+        //System.out.println("matchTag "+tagValue+" in "+caseStr);
+        for (int pos = 0, max = caseStr.length(), comma;
+                pos < max;
+                pos = comma + 1) {
+            int caseValue;
+            if (caseStr.charAt(pos) == '\\') {
+                caseValue = caseStr.charAt(pos + 1);
+                comma = pos + 2;
+                assert (comma == max || caseStr.charAt(comma) == ',');
+            } else {
+                comma = caseStr.indexOf(',', pos);
+                if (comma < 0) {
+                    comma = max;
+                }
+                caseValue = Integer.parseInt(caseStr.substring(pos, comma));
+            }
+            if (tagValue == caseValue) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    protected static String[] getBodies(String type) {
+        ArrayList<String> bodies = new ArrayList<String>();
+        for (int i = 0; i < type.length();) {
+            String body = getBody(type, i);
+            bodies.add(body);
+            i += body.length() + 2;  // skip body and brackets
+        }
+        return bodies.toArray(new String[bodies.size()]);
+    }
+
+    protected static String getBody(String type, int i) {
+        assert (type.charAt(i) == '[');
+        int next = ++i;  // skip bracket
+        for (int depth = 1; depth > 0; next++) {
+            switch (type.charAt(next)) {
+                case '[':
+                    depth++;
+                    break;
+                case ']':
+                    depth--;
+                    break;
+                case '(':
+                    next = type.indexOf(')', next);
+                    break;
+                case '<':
+                    next = type.indexOf('>', next);
+                    break;
+            }
+            assert (next > 0);
+        }
+        --next;  // get before bracket
+        assert (type.charAt(next) == ']');
+        return type.substring(i, next);
+    }
+
+    public Element makeCPDigest(int length) {
+        MessageDigest md;
+        try {
+            md = MessageDigest.getInstance("MD5");
+        } catch (java.security.NoSuchAlgorithmException ee) {
+            throw new Error(ee);
+        }
+        int items = 0;
+        for (Element e : cpool.elements()) {
+            if (items == length) {
+                break;
+            }
+            if (cpTagNames.contains(e.getName())) {
+                items += 1;
+                md.update((byte) cpTagValue(e.getName()));
+                try {
+                    md.update(e.getText().toString().getBytes(UTF8_ENCODING));
+                } catch (java.io.UnsupportedEncodingException ee) {
+                    throw new Error(ee);
+                }
+            }
+        }
+        ByteBuffer bb = ByteBuffer.wrap(md.digest());
+        String l0 = Long.toHexString(bb.getLong(0));
+        String l1 = Long.toHexString(bb.getLong(8));
+        while (l0.length() < 16) {
+            l0 = "0" + l0;
+        }
+        while (l1.length() < 16) {
+            l1 = "0" + l1;
+        }
+        return new Element("Digest",
+                "length", "" + items,
+                "bytes", l0 + l1);
+    }
+
+    public Element getCPDigest(int length) {
+        if (length == -1) {
+            length = cpool.countAll(XMLKit.elementFilter(cpTagNames));
+        }
+        for (Element md : cpool.findAllElements("Digest").elements()) {
+            if (md.getAttrLong("length") == length) {
+                return md;
+            }
+        }
+        Element md = makeCPDigest(length);
+        cpool.add(md);
+        return md;
+    }
+
+    public Element getCPDigest() {
+        return getCPDigest(-1);
+    }
+
+    public boolean checkCPDigest(Element md) {
+        return md.equals(getCPDigest((int) md.getAttrLong("length")));
+    }
+
+    public static int computeInterfaceNum(String intMethRef) {
+        intMethRef = intMethRef.substring(1 + intMethRef.lastIndexOf(' '));
+        if (!intMethRef.startsWith("(")) {
+            return -1;
+        }
+        int signum = 1;  // start with one for "this"
+        scanSig:
+        for (int i = 1; i < intMethRef.length(); i++) {
+            char ch = intMethRef.charAt(i);
+            signum++;
+            switch (ch) {
+                case ')':
+                    --signum;
+                    break scanSig;
+                case 'L':
+                    i = intMethRef.indexOf(';', i);
+                    break;
+                case '[':
+                    while (ch == '[') {
+                        ch = intMethRef.charAt(++i);
+                    }
+                    if (ch == 'L') {
+                        i = intMethRef.indexOf(';', i);
+                    }
+                    break;
+            }
+        }
+        int num = (signum << 8) | 0;
+        //System.out.println("computeInterfaceNum "+intMethRef+" => "+num);
+        return num;
+    }
+    // Protected state for representing the class file.
+    protected Element cfile;          // <ClassFile ...>
+    protected Element cpool;          // <ConstantPool ...>
+    protected Element klass;          // <Class ...>
+    protected Element currentMember;  // varies during scans
+    protected Element currentCode;    // varies during scans
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/pack200-verifier/src/xmlkit/ClassWriter.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,818 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
+
+import java.util.*;
+import java.lang.reflect.*;
+import java.io.*;
+import xmlkit.XMLKit.Element;
+/*
+ * @author jrose
+ */
+public class ClassWriter extends ClassSyntax implements ClassSyntax.GetCPIndex {
+
+    private static final CommandLineParser CLP = new CommandLineParser(""
+            + "-source:     +>  = \n"
+            + "-dest:       +>  = \n"
+            + "-encoding:   +>  = \n"
+            + "-parseBytes      $ \n"
+            + "-               *? \n"
+            + "\n");
+
+    public static void main(String[] ava) throws IOException {
+        ArrayList<String> av = new ArrayList<String>(Arrays.asList(ava));
+        HashMap<String, String> props = new HashMap<String, String>();
+        props.put("-encoding:", "UTF8");  // default
+        CLP.parse(av, props);
+        File source = asFile(props.get("-source:"));
+        File dest = asFile(props.get("-dest:"));
+        String encoding = props.get("-encoding:");
+        boolean parseBytes = props.containsKey("-parseBytes");
+        boolean destMade = false;
+
+        for (String a : av) {
+            File f;
+            File inf = new File(source, a);
+            System.out.println("Reading " + inf);
+            Element e;
+            if (inf.getName().endsWith(".class")) {
+                ClassReader cr = new ClassReader();
+                cr.parseBytes = parseBytes;
+                e = cr.readFrom(inf);
+                f = new File(a);
+            } else if (inf.getName().endsWith(".xml")) {
+                InputStream in = new FileInputStream(inf);
+                Reader inw = ClassReader.makeReader(in, encoding);
+                e = XMLKit.readFrom(inw);
+                e.findAllInTree(XMLKit.and(XMLKit.elementFilter(nonAttrTags()),
+                        XMLKit.methodFilter(Element.method("trimText"))));
+                //System.out.println(e);
+                inw.close();
+                f = new File(a.substring(0, a.length() - ".xml".length()) + ".class");
+            } else {
+                System.out.println("Warning: unknown input " + a);
+                continue;
+            }
+            // Now write it:
+            if (!destMade) {
+                destMade = true;
+                if (dest == null) {
+                    dest = File.createTempFile("TestOut", ".dir", new File("."));
+                    dest.delete();
+                    System.out.println("Writing results to " + dest);
+                }
+                if (!(dest.isDirectory() || dest.mkdir())) {
+                    throw new RuntimeException("Cannot create " + dest);
+                }
+            }
+            File outf = new File(dest, f.isAbsolute() ? f.getName() : f.getPath());
+            outf.getParentFile().mkdirs();
+            new ClassWriter(e).writeTo(outf);
+        }
+    }
+
+    private static File asFile(String str) {
+        return (str == null) ? null : new File(str);
+    }
+
+    public void writeTo(File file) throws IOException {
+        OutputStream out = null;
+        try {
+            out = new BufferedOutputStream(new FileOutputStream(file));
+            writeTo(out);
+        } finally {
+            if (out != null) {
+                out.close();
+            }
+        }
+    }
+    protected String[] callables;     // varies
+    protected int cpoolSize = 0;
+    protected HashMap<String, String> attrTypesByTag;
+    protected OutputStream out;
+    protected HashMap<String, int[]> cpMap = new HashMap<String, int[]>();
+    protected ArrayList<ByteArrayOutputStream> attrBufs = new ArrayList<ByteArrayOutputStream>();
+
+    private void setupAttrTypes() {
+        attrTypesByTag = new HashMap<String, String>();
+        for (String key : attrTypes.keySet()) {
+            String pfx = key.substring(0, key.indexOf('.') + 1);
+            String val = attrTypes.get(key);
+            int pos = val.indexOf('<');
+            if (pos >= 0) {
+                String tag = val.substring(pos + 1, val.indexOf('>', pos));
+                attrTypesByTag.put(pfx + tag, key);
+            }
+        }
+        //System.out.println("attrTypesByTag: "+attrTypesByTag);
+    }
+
+    protected ByteArrayOutputStream getAttrBuf() {
+        int nab = attrBufs.size();
+        if (nab == 0) {
+            return new ByteArrayOutputStream(1024);
+        }
+        ByteArrayOutputStream ab = attrBufs.get(nab - 1);
+        attrBufs.remove(nab - 1);
+        return ab;
+    }
+
+    protected void putAttrBuf(ByteArrayOutputStream ab) {
+        ab.reset();
+        attrBufs.add(ab);
+    }
+
+    public ClassWriter(Element root) {
+        this(root, null);
+    }
+
+    public ClassWriter(Element root, ClassSyntax cr) {
+        if (cr != null) {
+            attrTypes = cr.attrTypes;
+        }
+        setupAttrTypes();
+        if (root.getName() == "ClassFile") {
+            cfile = root;
+            cpool = root.findElement("ConstantPool");
+            klass = root.findElement("Class");
+        } else if (root.getName() == "Class") {
+            cfile = new Element("ClassFile",
+                    new String[]{
+                        "magic", String.valueOf(0xCAFEBABE),
+                        "minver", "0", "majver", "46",});
+            cpool = new Element("ConstantPool");
+            klass = root;
+        } else {
+            throw new IllegalArgumentException("bad element type " + root.getName());
+        }
+        if (cpool == null) {
+            cpool = new Element("ConstantPool");
+        }
+
+        int cpLen = 1 + cpool.size();
+        for (Element c : cpool.elements()) {
+            int id = (int) c.getAttrLong("id");
+            int tag = cpTagValue(c.getName());
+            setCPIndex(tag, c.getText().toString(), id);
+            switch (tag) {
+                case CONSTANT_Long:
+                case CONSTANT_Double:
+                    cpLen += 1;
+            }
+        }
+        cpoolSize = cpLen;
+    }
+
+    public int findCPIndex(int tag, String name) {
+        if (name == null) {
+            return 0;
+        }
+        int[] ids = cpMap.get(name.toString());
+        return (ids == null) ? 0 : ids[tag];
+    }
+
+    public int getCPIndex(int tag, String name) {
+        //System.out.println("getCPIndex "+cpTagName(tag)+" "+name);
+        if (name == null) {
+            return 0;
+        }
+        int id = findCPIndex(tag, name);
+        if (id == 0) {
+            id = cpoolSize;
+            cpoolSize += 1;
+            setCPIndex(tag, name, id);
+            cpool.add(new Element(cpTagName(tag),
+                    new String[]{"id", "" + id},
+                    new Object[]{name}));
+            int pos;
+            switch (tag) {
+                case CONSTANT_Long:
+                case CONSTANT_Double:
+                    cpoolSize += 1;
+                    break;
+                case CONSTANT_Class:
+                case CONSTANT_String:
+                    getCPIndex(CONSTANT_Utf8, name);
+                    break;
+                case CONSTANT_Fieldref:
+                case CONSTANT_Methodref:
+                case CONSTANT_InterfaceMethodref:
+                    pos = name.indexOf(' ');
+                    getCPIndex(CONSTANT_Class, name.substring(0, pos));
+                    getCPIndex(CONSTANT_NameAndType, name.substring(pos + 1));
+                    break;
+                case CONSTANT_NameAndType:
+                    pos = name.indexOf(' ');
+                    getCPIndex(CONSTANT_Utf8, name.substring(0, pos));
+                    getCPIndex(CONSTANT_Utf8, name.substring(pos + 1));
+                    break;
+            }
+        }
+        return id;
+    }
+
+    public void setCPIndex(int tag, String name, int id) {
+        //System.out.println("setCPIndex id="+id+" tag="+tag+" name="+name);
+        int[] ids = cpMap.get(name);
+        if (ids == null) {
+            cpMap.put(name, ids = new int[13]);
+        }
+        if (ids[tag] != 0 && ids[tag] != id) {
+            System.out.println("Warning: Duplicate CP entries for " + ids[tag] + " and " + id);
+        }
+        //assert(ids[tag] == 0 || ids[tag] == id);
+        ids[tag] = id;
+    }
+
+    public int parseFlags(String flagString) {
+        int flags = 0;
+        int i = -1;
+        for (String[] names : modifierNames) {
+            ++i;
+            for (String name : names) {
+                if (name == null) {
+                    continue;
+                }
+                int pos = flagString.indexOf(name);
+                if (pos >= 0) {
+                    flags |= (1 << i);
+                }
+            }
+        }
+        return flags;
+    }
+
+    public void writeTo(OutputStream realOut) throws IOException {
+        OutputStream headOut = realOut;
+        ByteArrayOutputStream tailOut = new ByteArrayOutputStream();
+
+        // write the body of the class file first
+        this.out = tailOut;
+        writeClass();
+
+        // write the file header last
+        this.out = headOut;
+        u4((int) cfile.getAttrLong("magic"));
+        u2((int) cfile.getAttrLong("minver"));
+        u2((int) cfile.getAttrLong("majver"));
+        writeCP();
+
+        // recopy the file tail
+        this.out = null;
+        tailOut.writeTo(realOut);
+    }
+
+    void writeClass() throws IOException {
+        int flags = parseFlags(klass.getAttr("flags"));
+        flags ^= Modifier.SYNCHRONIZED;
+        u2(flags);
+        cpRef(CONSTANT_Class, klass.getAttr("name"));
+        cpRef(CONSTANT_Class, klass.getAttr("super"));
+        Element interfaces = klass.findAllElements("Interface");
+        u2(interfaces.size());
+        for (Element e : interfaces.elements()) {
+            cpRef(CONSTANT_Class, e.getAttr("name"));
+        }
+        for (int isMethod = 0; isMethod <= 1; isMethod++) {
+            Element members = klass.findAllElements(isMethod != 0 ? "Method" : "Field");
+            u2(members.size());
+            for (Element m : members.elements()) {
+                writeMember(m, isMethod != 0);
+            }
+        }
+        writeAttributesFor(klass);
+    }
+
+    private void writeMember(Element member, boolean isMethod) throws IOException {
+        //System.out.println("writeMember "+member);
+        u2(parseFlags(member.getAttr("flags")));
+        cpRef(CONSTANT_Utf8, member.getAttr("name"));
+        cpRef(CONSTANT_Utf8, member.getAttr("type"));
+        writeAttributesFor(member);
+    }
+
+    protected void writeAttributesFor(Element x) throws IOException {
+        LinkedHashSet<String> attrNames = new LinkedHashSet<String>();
+        for (Element e : x.elements()) {
+            attrNames.add(e.getName());  // uniquifying
+        }
+        attrNames.removeAll(nonAttrTags());
+        u2(attrNames.size());
+        if (attrNames.isEmpty()) {
+            return;
+        }
+        Element prevCurrent;
+        if (x.getName() == "Code") {
+            prevCurrent = currentCode;
+            currentCode = x;
+        } else {
+            prevCurrent = currentMember;
+            currentMember = x;
+        }
+        OutputStream realOut = this.out;
+        for (String utag : attrNames) {
+            String qtag = x.getName() + "." + utag;
+            String wtag = "*." + utag;
+            String key = attrTypesByTag.get(qtag);
+            if (key == null) {
+                key = attrTypesByTag.get(wtag);
+            }
+            String type = attrTypes.get(key);
+            //System.out.println("tag "+qtag+" => key "+key+"; type "+type);
+            Element attrs = x.findAllElements(utag);
+            ByteArrayOutputStream attrBuf = getAttrBuf();
+            if (type == null) {
+                if (attrs.size() != 1 || !attrs.get(0).equals(new Element(utag))) {
+                    System.out.println("Warning:  No attribute type description: " + qtag);
+                }
+                key = wtag;
+            } else {
+                try {
+                    this.out = attrBuf;
+                    // unparse according to type desc.
+                    if (type.equals("<Code>...")) {
+                        writeCode((Element) attrs.get(0));  // assume only 1
+                    } else if (type.equals("<Frame>...")) {
+                        writeStackMap(attrs, false);
+                    } else if (type.equals("<FrameX>...")) {
+                        writeStackMap(attrs, true);
+                    } else if (type.startsWith("[")) {
+                        writeAttributeRecursive(attrs, type);
+                    } else {
+                        writeAttribute(attrs, type);
+                    }
+                } finally {
+                    //System.out.println("Attr Bytes = \""+attrBuf.toString(EIGHT_BIT_CHAR_ENCODING).replace('"', (char)('"'|0x80))+"\"");
+                    this.out = realOut;
+                }
+            }
+            cpRef(CONSTANT_Utf8, key.substring(key.indexOf('.') + 1));
+            u4(attrBuf.size());
+            attrBuf.writeTo(out);
+            putAttrBuf(attrBuf);
+        }
+        if (x.getName() == "Code") {
+            currentCode = prevCurrent;
+        } else {
+            currentMember = prevCurrent;
+        }
+    }
+
+    private void writeAttributeRecursive(Element aval, String type) throws IOException {
+        assert (callables == null);
+        callables = getBodies(type);
+        writeAttribute(aval, callables[0]);
+        callables = null;
+    }
+
+    private void writeAttribute(Element aval, String type) throws IOException {
+        //System.out.println("writeAttribute "+aval+"  using "+type);
+        String nextAttrName = null;
+        boolean afterElemHead = false;
+        for (int len = type.length(), next, i = 0; i < len; i = next) {
+            int value;
+            char intKind;
+            int tag;
+            int sigChar;
+            String attrValue;
+            switch (type.charAt(i)) {
+                case '<':
+                    assert (nextAttrName == null);
+                    next = type.indexOf('>', i);
+                    String form = type.substring(i + 1, next++);
+                    if (form.indexOf('=') < 0) {
+                        //  elem_placement = '<' elemname '>'
+                        if (aval.isAnonymous()) {
+                            assert (aval.size() == 1);
+                            aval = (Element) aval.get(0);
+                        }
+                        assert (aval.getName().equals(form)) : aval + " // " + form;
+                        afterElemHead = true;
+                    } else {
+                        //  attr_placement = '(' attrname '=' (value)? ')'
+                        int eqPos = form.indexOf('=');
+                        assert (eqPos >= 0);
+                        nextAttrName = form.substring(0, eqPos).intern();
+                        if (eqPos != form.length() - 1) {
+                            // value is implicit, not placed in file
+                            nextAttrName = null;
+                        }
+                        afterElemHead = false;
+                    }
+                    continue;
+                case '(':
+                    next = type.indexOf(')', ++i);
+                    int callee = Integer.parseInt(type.substring(i, next++));
+                    writeAttribute(aval, callables[callee]);
+                    continue;
+                case 'N': // replication = 'N' int '[' type ... ']'
+                {
+                    assert (nextAttrName == null);
+                    afterElemHead = false;
+                    char countType = type.charAt(i + 1);
+                    next = i + 2;
+                    String type1 = getBody(type, next);
+                    Element elems = aval;
+                    if (type1.startsWith("<")) {
+                        // Select only matching members of aval.
+                        String elemName = type1.substring(1, type1.indexOf('>'));
+                        elems = aval.findAllElements(elemName);
+                    }
+                    putInt(elems.size(), countType);
+                    next += type1.length() + 2;  // skip body and brackets
+                    for (Element elem : elems.elements()) {
+                        writeAttribute(elem, type1);
+                    }
+                }
+                continue;
+                case 'T': // union = 'T' any_int union_case* '(' ')' '[' body ']'
+                    // write the value
+                    value = (int) aval.getAttrLong("tag");
+                    assert (aval.getAttr("tag") != null) : aval;
+                    intKind = type.charAt(++i);
+                    if (intKind == 'S') {
+                        intKind = type.charAt(++i);
+                    }
+                    putInt(value, intKind);
+                    nextAttrName = null;
+                    afterElemHead = false;
+                    ++i;  // skip the int type char
+                    // union_case = '(' ('-')? digit+ ')' '[' body ']'
+                    for (boolean foundCase = false;;) {
+                        assert (type.charAt(i) == '(');
+                        next = type.indexOf(')', ++i);
+                        assert (next >= i);
+                        String caseStr = type.substring(i, next++);
+                        String type1 = getBody(type, next);
+                        next += type1.length() + 2;  // skip body and brackets
+                        boolean lastCase = (caseStr.length() == 0);
+                        if (!foundCase
+                                && (lastCase || matchTag(value, caseStr))) {
+                            foundCase = true;
+                            // Execute this body.
+                            writeAttribute(aval, type1);
+                        }
+                        if (lastCase) {
+                            break;
+                        }
+                    }
+                    continue;
+                case 'B':
+                case 'H':
+                case 'I': // int = oneof "BHI"
+                    value = (int) aval.getAttrLong(nextAttrName);
+                    intKind = type.charAt(i);
+                    next = i + 1;
+                    break;
+                case 'K':
+                    sigChar = type.charAt(i + 1);
+                    if (sigChar == 'Q') {
+                        assert (currentMember.getName() == "Field");
+                        assert (aval.getName() == "ConstantValue");
+                        String sig = currentMember.getAttr("type");
+                        sigChar = sig.charAt(0);
+                        switch (sigChar) {
+                            case 'Z':
+                            case 'B':
+                            case 'C':
+                            case 'S':
+                                sigChar = 'I';
+                                break;
+                        }
+                    }
+                    switch (sigChar) {
+                        case 'I':
+                            tag = CONSTANT_Integer;
+                            break;
+                        case 'J':
+                            tag = CONSTANT_Long;
+                            break;
+                        case 'F':
+                            tag = CONSTANT_Float;
+                            break;
+                        case 'D':
+                            tag = CONSTANT_Double;
+                            break;
+                        case 'L':
+                            tag = CONSTANT_String;
+                            break;
+                        default:
+                            assert (false);
+                            tag = 0;
+                    }
+                    assert (type.charAt(i + 2) == 'H');  // only H works for now
+                    next = i + 3;
+                    assert (afterElemHead || nextAttrName != null);
+                    //System.out.println("get attr "+nextAttrName+" in "+aval);
+                    if (nextAttrName != null) {
+                        attrValue = aval.getAttr(nextAttrName);
+                        assert (attrValue != null);
+                    } else {
+                        assert (aval.isText()) : aval;
+                        attrValue = aval.getText().toString();
+                    }
+                    value = getCPIndex(tag, attrValue);
+                    intKind = 'H'; //type.charAt(i+2);
+                    break;
+                case 'R':
+                    sigChar = type.charAt(i + 1);
+                    switch (sigChar) {
+                        case 'C':
+                            tag = CONSTANT_Class;
+                            break;
+                        case 'S':
+                            tag = CONSTANT_Utf8;
+                            break;
+                        case 'D':
+                            tag = CONSTANT_Class;
+                            break;
+                        case 'F':
+                            tag = CONSTANT_Fieldref;
+                            break;
+                        case 'M':
+                            tag = CONSTANT_Methodref;
+                            break;
+                        case 'I':
+                            tag = CONSTANT_InterfaceMethodref;
+                            break;
+                        case 'U':
+                            tag = CONSTANT_Utf8;
+                            break;
+                        //case 'Q': tag = CONSTANT_Class; break;
+                        default:
+                            assert (false);
+                            tag = 0;
+                    }
+                    assert (type.charAt(i + 2) == 'H');  // only H works for now
+                    next = i + 3;
+                    assert (afterElemHead || nextAttrName != null);
+                    //System.out.println("get attr "+nextAttrName+" in "+aval);
+                    if (nextAttrName != null) {
+                        attrValue = aval.getAttr(nextAttrName);
+                    } else if (aval.hasText()) {
+                        attrValue = aval.getText().toString();
+                    } else {
+                        attrValue = null;
+                    }
+                    value = getCPIndex(tag, attrValue);
+                    intKind = 'H'; //type.charAt(i+2);
+                    break;
+                case 'P':  // bci = 'P' int
+                case 'S':  // signed_int = 'S' int
+                    next = i + 2;
+                    value = (int) aval.getAttrLong(nextAttrName);
+                    intKind = type.charAt(i + 1);
+                    break;
+                case 'F':
+                    next = i + 2;
+                    value = parseFlags(aval.getAttr(nextAttrName));
+                    intKind = type.charAt(i + 1);
+                    break;
+                default:
+                    throw new RuntimeException("bad attr format '" + type.charAt(i) + "': " + type);
+            }
+            // write the value
+            putInt(value, intKind);
+            nextAttrName = null;
+            afterElemHead = false;
+        }
+        assert (nextAttrName == null);
+    }
+
+    private void putInt(int x, char ch) throws IOException {
+        switch (ch) {
+            case 'B':
+                u1(x);
+                break;
+            case 'H':
+                u2(x);
+                break;
+            case 'I':
+                u4(x);
+                break;
+        }
+        assert ("BHI".indexOf(ch) >= 0);
+    }
+
+    private void writeCode(Element code) throws IOException {
+        //System.out.println("writeCode "+code);
+        //Element m = new Element(currentMember); m.remove(code);
+        //System.out.println("       in "+m);
+        int stack = (int) code.getAttrLong("stack");
+        int local = (int) code.getAttrLong("local");
+        Element bytes = code.findElement("Bytes");
+        Element insns = code.findElement("Instructions");
+        String bytecodes;
+        if (insns == null) {
+            bytecodes = bytes.getText().toString();
+        } else {
+            bytecodes = InstructionSyntax.assemble(insns, this);
+            // Cache the assembled bytecodes:
+            bytes = new Element("Bytes", (String[]) null, bytecodes);
+            code.add(0, bytes);
+        }
+        u2(stack);
+        u2(local);
+        int length = bytecodes.length();
+        u4(length);
+        for (int i = 0; i < length; i++) {
+            u1((byte) bytecodes.charAt(i));
+        }
+        Element handlers = code.findAllElements("Handler");
+        u2(handlers.size());
+        for (Element handler : handlers.elements()) {
+            int start = (int) handler.getAttrLong("start");
+            int end = (int) handler.getAttrLong("end");
+            int catsh = (int) handler.getAttrLong("catch");
+            u2(start);
+            u2(end);
+            u2(catsh);
+            cpRef(CONSTANT_Class, handler.getAttr("class"));
+        }
+        writeAttributesFor(code);
+    }
+
+    protected void writeStackMap(Element attrs, boolean hasXOption) throws IOException {
+        Element bytes = currentCode.findElement("Bytes");
+        assert (bytes != null && bytes.size() == 1);
+        int byteLength = ((String) bytes.get(0)).length();
+        boolean uoffsetIsU4 = (byteLength >= (1 << 16));
+        boolean ulocalvarIsU4 = currentCode.getAttrLong("local") >= (1 << 16);
+        boolean ustackIsU4 = currentCode.getAttrLong("stack") >= (1 << 16);
+        if (uoffsetIsU4) {
+            u4(attrs.size());
+        } else {
+            u2(attrs.size());
+        }
+        for (Element frame : attrs.elements()) {
+            int bci = (int) frame.getAttrLong("bci");
+            if (uoffsetIsU4) {
+                u4(bci);
+            } else {
+                u2(bci);
+            }
+            if (hasXOption) {
+                u1((int) frame.getAttrLong("flags"));
+            }
+            // Scan local and stack types in this frame:
+            final int LOCALS = 0, STACK = 1;
+            for (int j = LOCALS; j <= STACK; j++) {
+                Element types = frame.findElement(j == LOCALS ? "Local" : "Stack");
+                int typeSize = (types == null) ? 0 : types.size();
+                if (j == LOCALS) {
+                    if (ulocalvarIsU4) {
+                        u4(typeSize);
+                    } else {
+                        u2(typeSize);
+                    }
+                } else { // STACK
+                    if (ustackIsU4) {
+                        u4(typeSize);
+                    } else {
+                        u2(typeSize);
+                    }
+                }
+                if (types == null) {
+                    continue;
+                }
+                for (Element type : types.elements()) {
+                    int tag = itemTagValue(type.getName());
+                    u1(tag);
+                    switch (tag) {
+                        case ITEM_Object:
+                            cpRef(CONSTANT_Class, type.getAttr("class"));
+                            break;
+                        case ITEM_Uninitialized:
+                        case ITEM_ReturnAddress: {
+                            int offset = (int) type.getAttrLong("bci");
+                            if (uoffsetIsU4) {
+                                u4(offset);
+                            } else {
+                                u2(offset);
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    public void writeCP() throws IOException {
+        int cpLen = cpoolSize;
+        u2(cpLen);
+        ByteArrayOutputStream buf = getAttrBuf();
+        for (Element c : cpool.elements()) {
+            if (!c.isText()) {
+                System.out.println("## !isText " + c);
+            }
+            int id = (int) c.getAttrLong("id");
+            int tag = cpTagValue(c.getName());
+            String name = c.getText().toString();
+            int pos;
+            u1(tag);
+            switch (tag) {
+                case CONSTANT_Utf8: {
+                    int done = 0;
+                    buf.reset();
+                    int nameLen = name.length();
+                    while (done < nameLen) {
+                        int next = name.indexOf((char) 0, done);
+                        if (next < 0) {
+                            next = nameLen;
+                        }
+                        if (done < next) {
+                            buf.write(name.substring(done, next).getBytes(UTF8_ENCODING));
+                        }
+                        if (next < nameLen) {
+                            buf.write(0300);
+                            buf.write(0200);
+                            next++;
+                        }
+                        done = next;
+                    }
+                    u2(buf.size());
+                    buf.writeTo(out);
+                }
+                break;
+                case CONSTANT_Integer:
+                    u4(Integer.parseInt(name));
+                    break;
+                case CONSTANT_Float:
+                    u4(Float.floatToIntBits(Float.parseFloat(name)));
+                    break;
+                case CONSTANT_Long:
+                    u8(Long.parseLong(name));
+                    //i += 1;  // no need:  extra cp slot is implicit
+                    break;
+                case CONSTANT_Double:
+                    u8(Double.doubleToLongBits(Double.parseDouble(name)));
+                    //i += 1;  // no need:  extra cp slot is implicit
+                    break;
+                case CONSTANT_Class:
+                case CONSTANT_String:
+                    u2(getCPIndex(CONSTANT_Utf8, name));
+                    break;
+                case CONSTANT_Fieldref:
+                case CONSTANT_Methodref:
+                case CONSTANT_InterfaceMethodref:
+                    pos = name.indexOf(' ');
+                    u2(getCPIndex(CONSTANT_Class, name.substring(0, pos)));
+                    u2(getCPIndex(CONSTANT_NameAndType, name.substring(pos + 1)));
+                    break;
+                case CONSTANT_NameAndType:
+                    pos = name.indexOf(' ');
+                    u2(getCPIndex(CONSTANT_Utf8, name.substring(0, pos)));
+                    u2(getCPIndex(CONSTANT_Utf8, name.substring(pos + 1)));
+                    break;
+            }
+        }
+        putAttrBuf(buf);
+    }
+
+    public void cpRef(int tag, String name) throws IOException {
+        u2(getCPIndex(tag, name));
+    }
+
+    public void u8(long x) throws IOException {
+        u4((int) (x >>> 32));
+        u4((int) (x >>> 0));
+    }
+
+    public void u4(int x) throws IOException {
+        u2(x >>> 16);
+        u2(x >>> 0);
+    }
+
+    public void u2(int x) throws IOException {
+        u1(x >>> 8);
+        u1(x >>> 0);
+    }
+
+    public void u1(int x) throws IOException {
+        out.write(x & 0xFF);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/pack200-verifier/src/xmlkit/CommandLineParser.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
+
+import java.util.*;
+/*
+ * @author jrose
+ */
+public class CommandLineParser {
+
+    public CommandLineParser(String optionString) {
+        setOptionMap(optionString);
+    }
+    TreeMap<String, String[]> optionMap;
+
+    public void setOptionMap(String options) {
+        // Convert options string into optLines dictionary.
+        TreeMap<String, String[]> optmap = new TreeMap<String, String[]>();
+        loadOptmap:
+        for (String optline : options.split("\n")) {
+            String[] words = optline.split("\\p{Space}+");
+            if (words.length == 0) {
+                continue loadOptmap;
+            }
+            String opt = words[0];
+            words[0] = "";  // initial word is not a spec
+            if (opt.length() == 0 && words.length >= 1) {
+                opt = words[1];  // initial "word" is empty due to leading ' '
+                words[1] = "";
+            }
+            if (opt.length() == 0) {
+                continue loadOptmap;
+            }
+            String[] prevWords = optmap.put(opt, words);
+            if (prevWords != null) {
+                throw new RuntimeException("duplicate option: "
+                        + optline.trim());
+            }
+        }
+        optionMap = optmap;
+    }
+
+    public String getOptionMap() {
+        TreeMap<String, String[]> optmap = optionMap;
+        StringBuffer sb = new StringBuffer();
+        for (String opt : optmap.keySet()) {
+            sb.append(opt);
+            for (String spec : optmap.get(opt)) {
+                sb.append(' ').append(spec);
+            }
+            sb.append('\n');
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Remove a set of command-line options from args,
+     * storing them in the properties map in a canonicalized form.
+     */
+    public String parse(List<String> args, Map<String, String> properties) {
+        //System.out.println(args+" // "+properties);
+
+        String resultString = null;
+        TreeMap<String, String[]> optmap = optionMap;
+
+        // State machine for parsing a command line.
+        ListIterator<String> argp = args.listIterator();
+        ListIterator<String> pbp = new ArrayList<String>().listIterator();
+        doArgs:
+        for (;;) {
+            // One trip through this loop per argument.
+            // Multiple trips per option only if several options per argument.
+            String arg;
+            if (pbp.hasPrevious()) {
+                arg = pbp.previous();
+                pbp.remove();
+            } else if (argp.hasNext()) {
+                arg = argp.next();
+            } else {
+                // No more arguments at all.
+                break doArgs;
+            }
+            tryOpt:
+            for (int optlen = arg.length();; optlen--) {
+                // One time through this loop for each matching arg prefix.
+                String opt;
+                // Match some prefix of the argument to a key in optmap.
+                findOpt:
+                for (;;) {
+                    opt = arg.substring(0, optlen);
+                    if (optmap.containsKey(opt)) {
+                        break findOpt;
+                    }
+                    if (optlen == 0) {
+                        break tryOpt;
+                    }
+                    // Decide on a smaller prefix to search for.
+                    SortedMap<String, String[]> pfxmap = optmap.headMap(opt);
+                    // pfxmap.lastKey is no shorter than any prefix in optmap.
+                    int len = pfxmap.isEmpty() ? 0 : pfxmap.lastKey().length();
+                    optlen = Math.min(len, optlen - 1);
+                    opt = arg.substring(0, optlen);
+                    // (Note:  We could cut opt down to its common prefix with
+                    // pfxmap.lastKey, but that wouldn't save many cycles.)
+                }
+                opt = opt.intern();
+                assert (arg.startsWith(opt));
+                assert (opt.length() == optlen);
+                String val = arg.substring(optlen);  // arg == opt+val
+
+                // Execute the option processing specs for this opt.
+                // If no actions are taken, then look for a shorter prefix.
+                boolean didAction = false;
+                boolean isError = false;
+
+                int pbpMark = pbp.nextIndex();  // in case of backtracking
+                String[] specs = optmap.get(opt);
+                eachSpec:
+                for (String spec : specs) {
+                    if (spec.length() == 0) {
+                        continue eachSpec;
+                    }
+                    if (spec.startsWith("#")) {
+                        break eachSpec;
+                    }
+                    int sidx = 0;
+                    char specop = spec.charAt(sidx++);
+
+                    // Deal with '+'/'*' prefixes (spec conditions).
+                    boolean ok;
+                    switch (specop) {
+                        case '+':
+                            // + means we want an non-empty val suffix.
+                            ok = (val.length() != 0);
+                            specop = spec.charAt(sidx++);
+                            break;
+                        case '*':
+                            // * means we accept empty or non-empty
+                            ok = true;
+                            specop = spec.charAt(sidx++);
+                            break;
+                        default:
+                            // No condition prefix means we require an exact
+                            // match, as indicated by an empty val suffix.
+                            ok = (val.length() == 0);
+                            break;
+                    }
+                    if (!ok) {
+                        continue eachSpec;
+                    }
+
+                    String specarg = spec.substring(sidx);
+                    switch (specop) {
+                        case '.':  // terminate the option sequence
+                            resultString = (specarg.length() != 0) ? specarg.intern() : opt;
+                            break doArgs;
+                        case '?':  // abort the option sequence
+                            resultString = (specarg.length() != 0) ? specarg.intern() : arg;
+                            isError = true;
+                            break eachSpec;
+                        case '@':  // change the effective opt name
+                            opt = specarg.intern();
+                            break;
+                        case '>':  // shift remaining arg val to next arg
+                            pbp.add(specarg + val);  // push a new argument
+                            val = "";
+                            break;
+                        case '!':  // negation option
+                            String negopt = (specarg.length() != 0) ? specarg.intern() : opt;
+                            properties.remove(negopt);
+                            properties.put(negopt, null);  // leave placeholder
+                            didAction = true;
+                            break;
+                        case '$':  // normal "boolean" option
+                            String boolval;
+                            if (specarg.length() != 0) {
+                                // If there is a given spec token, store it.
+                                boolval = specarg;
+                            } else {
+                                String old = properties.get(opt);
+                                if (old == null || old.length() == 0) {
+                                    boolval = "1";
+                                } else {
+                                    // Increment any previous value as a numeral.
+                                    boolval = "" + (1 + Integer.parseInt(old));
+                                }
+                            }
+                            properties.put(opt, boolval);
+                            didAction = true;
+                            break;
+                        case '=':  // "string" option
+                        case '&':  // "collection" option
+                            // Read an option.
+                            boolean append = (specop == '&');
+                            String strval;
+                            if (pbp.hasPrevious()) {
+                                strval = pbp.previous();
+                                pbp.remove();
+                            } else if (argp.hasNext()) {
+                                strval = argp.next();
+                            } else {
+                                resultString = arg + " ?";
+                                isError = true;
+                                break eachSpec;
+                            }
+                            if (append) {
+                                String old = properties.get(opt);
+                                if (old != null) {
+                                    // Append new val to old with embedded delim.
+                                    String delim = specarg;
+                                    if (delim.length() == 0) {
+                                        delim = " ";
+                                    }
+                                    strval = old + specarg + strval;
+                                }
+                            }
+                            properties.put(opt, strval);
+                            didAction = true;
+                            break;
+                        default:
+                            throw new RuntimeException("bad spec for "
+                                    + opt + ": " + spec);
+                    }
+                }
+
+                // Done processing specs.
+                if (didAction && !isError) {
+                    continue doArgs;
+                }
+
+                // The specs should have done something, but did not.
+                while (pbp.nextIndex() > pbpMark) {
+                    // Remove anything pushed during these specs.
+                    pbp.previous();
+                    pbp.remove();
+                }
+
+                if (isError) {
+                    throw new IllegalArgumentException(resultString);
+                }
+
+                if (optlen == 0) {
+                    // We cannot try a shorter matching option.
+                    break tryOpt;
+                }
+            }
+
+            // If we come here, there was no matching option.
+            // So, push back the argument, and return to caller.
+            pbp.add(arg);
+            break doArgs;
+        }
+        // Report number of arguments consumed.
+        args.subList(0, argp.nextIndex()).clear();
+        // Report any unconsumed partial argument.
+        while (pbp.hasPrevious()) {
+            args.add(0, pbp.previous());
+        }
+        //System.out.println(args+" // "+properties+" -> "+resultString);
+        return resultString;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/pack200/pack200-verifier/src/xmlkit/InstructionAssembler.java	Mon Aug 23 19:14:20 2010 -0700
@@ -0,0 +1,464 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
+
+import xmlkit.XMLKit.Element;
+import java.util.HashMap;
+/*
+ * @author jrose
+ */
+abstract class InstructionAssembler extends InstructionSyntax {
+
+    InstructionAssembler() {
+    }
+
+    public static String assemble(Element instructions, String pcAttrName,
+            ClassSyntax.GetCPIndex getCPI) {
+        int insCount = instructions.size();
+        Element[] insElems = new Element[insCount];
+        int[] elemToIndexMap;
+        int[] insLocs;
+        byte[] ops = new byte[insCount];
+        int[] operands = new int[insCount];
+        boolean[] isWide = new boolean[insCount];
+        int[] branches;
+        int[] branchInsLocs;
+        HashMap<String, String> labels = new HashMap<String, String>();
+
+        final int WIDE = 0xc4;
+        final int GOTO = 0xa7;
+        final int GOTO_W = 0xc8;
+        final int GOTO_LEN = 3;
+        final int GOTO_W_LEN = 5;
+        assert ("wide".equals(bcNames[WIDE]));
+        assert ("goto".equals(bcNames[GOTO]));
+        assert ("goto_w".equals(bcNames[GOTO_W]));
+        assert (bcFormats[GOTO].length() == GOTO_LEN);
+        assert (bcFormats[GOTO_W].length() == GOTO_W_LEN);
+
+        // Unpack instructions into temp. arrays, and find branches and labels.
+        {
+            elemToIndexMap = (pcAttrName != null) ? new int[insCount] : null;
+            int[] buffer = operands;
+            int id = 0;
+            int branchCount = 0;
+            for (int i = 0; i < insCount; i++) {
+                Element ins = (Element) instructions.get(i);
+                if (elemToIndexMap != null) {
+                    elemToIndexMap[i] = (ins.getAttr(pcAttrName) != null ? id : -1);
+                }
+                String lab = ins.getAttr("pc");
+                if (lab != null) {
+                    labels.put(lab, String.valueOf(id));
+                }
+                int op = opCode(ins.getName());
+                if (op < 0) {
+                    assert (ins.getAttr(pcAttrName) != null
+                            || ins.getName().equals("label"));
+                    continue;  // delete PC holder element
+                }
+                if (op == WIDE) { //0xc4
+                    isWide[id] = true;  // force wide format
+                    continue;
+                }
+                if (bcFormats[op].indexOf('o') >= 0) {
+                    buffer[branchCount++] = id;
+                }
+                if (bcFormats[op] == bcWideFormats[op]) {
+                    isWide[id] = false;
+                }
+                insElems[id] = ins;
+                ops[id] = (byte) op;
+                id++;
+            }
+            insCount = id;  // maybe we deleted some wide prefixes, etc.
+            branches = new int[branchCount + 1];
+            System.arraycopy(buffer, 0, branches, 0, branchCount);
+            branches[branchCount] = -1;  // sentinel
+        }
+
+        // Compute instruction sizes.  These sizes are final,
+        // except for branch instructions, which may need lengthening.
+        // Some instructions (ldc, bipush, iload, iinc) are automagically widened.
+        insLocs = new int[insCount + 1];
+        int loc = 0;
+        for (int bn = 0, id = 0; id < insCount; id++) {
+            insLocs[id] = loc;
+            Element ins = insElems[id];
+            int op = ops[id] & 0xFF;
+            String format = opFormat(op, isWide[id]);
+            // Make sure operands fit within the given format.
+            for (int j = 1, jlimit = format.length(); j < jlimit; j++) {
+                char fc = format.charAt(j);
+                int x = 0;
+                switch (fc) {
+                    case 'l':
+                        x = (int) ins.getAttrLong("loc");
+                        assert (x >= 0);
+                        if (x > 0xFF && !isWide[id]) {
+                            isWide[id] = true;
+                            format = opFormat(op, isWide[id]);
+                        }
+                        assert (x <= 0xFFFF);
+                        break;
+                    case 'k':
+                        char fc2 = format.charAt(Math.min(j + 1, format.length() - 1));
+                        x = getCPIndex(ins, fc2, getCPI);
+                        if (x > 0xFF && j == jlimit - 1) {
+                            assert (op == 0x12); //ldc
+                            ops[id] = (byte) (op = 0x13); //ldc_w
+                            format = opFormat(op);
+                        }
+                        assert (x <= 0xFFFF);
+                        j++;  // skip type-of-constant marker
+                        break;
+                    case 'x':
+                        x = (int) ins.getAttrLong("num");
+                        assert (x >= 0 && x <= ((j == jlimit - 1) ? 0xFF : 0xFFFF));
+                        break;
+                    case 's':
+                        x = (int) ins.getAttrLong("num");
+                        if (x != (byte) x && j == jlimit - 1) {
+                            switch (op) {
+                                case 0x10: //bipush
+                                    ops[id] = (byte) (op = 0x11); //sipush
+                                    break;
+                                case 0x84: //iinc
+                                    isWide[id] = true;
+                                    format = opFormat(op, isWide[id]);
+                                    break;
+                                default:
+                                    assert (false);  // cannot lengthen
+                            }
+                        }
+                        // unsign the value now, to make later steps clearer
+                        if (j == jlimit - 1) {
+                            assert (x == (byte) x);
+                            x = x & 0xFF;
+                        } else {
+                            assert (x == (short) x);
+                            x = x & 0xFFFF;
+                        }
+                        break;
+                    case 'o':
+                        assert (branches[bn] == id);
+                        bn++;
+                        // make local copies of the branches, and fix up labels
+                        insElems[id] = ins = new Element(ins);
+                        String newLab = labels.get(ins.getAttr("lab"));
+                        assert (newLab != null);
+                        ins.setAttr("lab", newLab);
+                        int prevCas = 0;
+                        int k = 0;
+                        for (Element cas : ins.elements()) {
+                            assert (cas.getName().equals("Case"));
+                            ins.set(k++, cas = new Element(cas));
+                            newLab = labels.get(cas.getAttr("lab"));
+                            assert (newLab != null);
+                            cas.setAttr("lab", newLab);
+                            int thisCas = (int) cas.getAttrLong("num");
+                            assert (op == 0xab
+                                    || op == 0xaa && (k == 0 || thisCas == prevCas + 1));
+                            prevCas = thisCas;
+                        }
+                        break;
+                    case 't':
+                        // switch table is represented as Switch.Case sub-elements
+                        break;
+                    default:
+                        assert (false);
+                }
+                operands[id] = x;  // record operand (last if there are 2)
+                // skip redundant chars
+                while (j + 1 < jlimit && format.charAt(j + 1) == fc) {
+                    ++j;
+                }
+            }
+
+            switch (op) {
+                case 0xaa: //tableswitch
+                    loc = switchBase(loc);
+                    loc += 4 * (3 + ins.size());
+                    break;
+                case 0xab: //lookupswitch
+                    loc = switchBase(loc);
+                    loc += 4 * (2 + 2 * ins.size());
+                    break;
+                default:
+                    if (isWide[id]) {
+                        loc++;  // 'wide' opcode prefix
+                    }
+                    loc += format.length();
+                    break;
+            }
+        }
+        insLocs[insCount] = loc;
+
+        // compute branch offsets, and see if any branches need expansion
+        for (int maxTries = 9, tries = 0;; ++tries) {
+            boolean overflowing = false;
+            boolean[] branchExpansions = null;
+            for (int bn = 0; bn < branches.length - 1; bn++) {
+                int id = branches[bn];
+                Element ins = insElems[id];
+                int insSize = insLocs[id + 1] - insLocs[id];
+                int origin = insLocs[id];
+                int target = insLocs[(int) ins.getAttrLong("lab")];
+                int offset = target - origin;
+                operands[id] = offset;
+                //System.out.println("branch id="+id+" len="+insSize+" to="+target+" offset="+offset);
+                assert (insSize == GOTO_LEN || insSize == GOTO_W_LEN || ins.getName().indexOf("switch") > 0);
+                boolean thisOverflow = (insSize == GOTO_LEN && (offset != (short) offset));
+                if (thisOverflow && !overflowing) {
+                    overflowing = true;
+                    branchExpansions = new boolean[branches.length];
+                }
+                if (thisOverflow || tries == maxTries - 1) {
+                    // lengthen the branch
+                    assert (!(thisOverflow && isWide[id]));
+                    isWide[id] = true;
+                    branchExpansions[bn] = true;
+                }
+            }
+            if (!overflowing) {
+                break;  // done, usually on first try
+            }
+            assert (tries <= maxTries);
+
+            // Walk over all instructions, expanding branches and updating locations.
+            int fixup = 0;
+            for (int bn = 0, id = 0; id < insCount; id++) {
+                insLocs[id] += fixup;
+                if (branches[bn] == id) {
+                    int op = ops[id] & 0xFF;
+                    int wop;
+                    boolean invert;
+                    if (branchExpansions[bn]) {
+                        switch (op) {
+                            case GOTO: //0xa7
+                                wop = GOTO_W; //0xc8
+                                invert = false;
+                                break;
+                            case 0xa8: //jsr
+                                wop = 0xc9; //jsr_w
+                                invert = false;
+                                break;
+                            default:
+                                wop = invertBranchOp(op);
+                                invert = true;
+                                break;
+                        }
+                        assert (op != wop);
+                        ops[id] = (byte) wop;
+                        isWide[id] = invert;
+                        if (invert) {
+                            fixup += GOTO_W_LEN;  //branch around a wide goto
+                        } else {
+                            fixup += (GOTO_W_LEN - GOTO_LEN);
+                        }
+                        // done expanding:  ops and isWide reflect the decision
+                    }
+                    bn++;
+                }
+            }
+            insLocs[insCount] += fixup;
+        }
+        // we know the layout now
+
+        // notify the caller of offsets, if requested
+        if (elemToIndexMap != null) {
+            for (int i = 0; i < elemToIndexMap.length; i++) {
+                int id = elemToIndexMap[i];
+                if (id >= 0) {
+                    Element ins = (Element) instructions.get(i);
+                    ins.setAttr(pcAttrName, "" + insLocs[id]);
+                }
+            }
+            elemToIndexMap = null;  // release the pointer
+        }
+
+        // output the bytes
+        StringBuffer sbuf = new StringBuffer(insLocs[insCount]);
+        for (int bn = 0, id = 0; id < insCount; id++) {
+            //System.out.println("output id="+id+" loc="+insLocs[id]+" len="+(insLocs[id+1]-insLocs[id])+" #sbuf="+sbuf.length());
+            assert (sbuf.length() == insLocs[id]);
+            Element ins;
+            int pc = insLocs[id];
+            int nextpc = insLocs[id + 1];
+            int op = ops[id] & 0xFF;
+            int opnd = operands[id];
+            String format;
+            if (branches[bn] == id) {
+                bn++;
+                sbuf.append((char) op);
+                if (isWide[id]) {
+                    // emit <ifop lab=1f> <goto_w target> <label pc=1f>
+                    int target = pc + opnd;
+                    putInt(sbuf, nextpc - pc, -2);
+                    assert (sbuf.length() == pc + GOTO_LEN);
+                    sbuf.append((char) GOTO_W);
+                    putInt(sbuf, target - (pc + GOTO_LEN), 4);
+                } else if (op == 0xaa || //tableswitch
+                        op == 0xab) {  //lookupswitch
+                    ins = insElems[id];
+                    for (int pad = switchBase(pc) - (pc + 1); pad > 0; pad--) {
+                        sbuf.append((char) 0);
+                    }
+                    assert (pc + opnd == insLocs[(int) ins.getAttrLong("lab")]);
+                    putInt(sbuf, opnd, 4); // default label
+                    if (op == 0xaa) {  //tableswitch
+                        Element cas0 = (Element) ins.get(0);
+                        int lowCase = (int) cas0.getAttrLong("num");
+                        Element casN = (Element) ins.get(ins.size() - 1);
+                        int highCase = (int) casN.getAttrLong("num");
+                        assert (highCase - lowCase + 1 == ins.size());
+                        putInt(sbuf, lowCase, 4);
+                        putInt(sbuf, highCase, 4);
+                        int caseForAssert = lowCase;
+                        for (Element cas : ins.elements()) {
+                            int target = insLocs[(int) cas.getAttrLong("lab")];
+                            assert (cas.getAttrLong("num") == caseForAssert++);
+                            putInt(sbuf, target - pc, 4);
+                        }
+                    } else {  //lookupswitch
+                        int caseCount = ins.size();
+                        putInt(sbuf, caseCount, 4);
+                        for (Element cas : ins.elements()) {
+                            int target = insLocs[(int) cas.getAttrLong("lab")];
+                            putInt(sbuf, (int) cas.getAttrLong("num"), 4);
+                            putInt(sbuf, target - pc, 4);
+                        }
+                    }
+                    assert (nextpc == sbuf.length());
+                } else {
+                    putInt(sbuf, opnd, -(nextpc - (pc + 1)));
+                }
+            } else if (nextpc == pc + 1) {
+                // a single-byte instruction
+                sbuf.append((char) op);
+            } else {
+                // picky stuff
+                boolean wide = isWide[id];
+                if (wide) {
+                    sbuf.append((char) WIDE);
+                    pc++;
+                }
+                sbuf.append((char) op);
+                int opnd1;
+                int opnd2 = opnd;
+                switch (op) {
+                    case 0x84:  //iinc
+                        ins = insElems[id];
+                        opnd1 = (int) ins.getAttrLong("loc");
+                        if (isWide[id]) {
+                            putInt(sbuf, opnd1, 2);
+                            putInt(sbuf, opnd2, 2);
+                        } else {
+                            putInt(sbuf, opnd1, 1);
+                            putInt(sbuf, opnd2, 1);
+                        }
+                        break;
+                    case 0xc5: //multianewarray
+                        ins = insElems[id];
+                        opnd1 = getCPIndex(ins, 'c', getCPI);
+                        putInt(sbuf, opnd1, 2);
+                        putInt(sbuf, opnd2, 1);
+                        break;
+                    case 0xb9: //invokeinterface
+                        ins = insElems[id];
+                        opnd1 = getCPIndex(ins, 'n', getCPI);
+                        putInt(sbuf, opnd1, 2);
+                        opnd2 = (int) ins.getAttrLong("num");
+                        if (opnd2 == 0) {
+                            opnd2 = ClassSyntax.computeInterfaceNum(ins.getAttr("val"));
+                        }
+                        putInt(sbuf, opnd2, 2);
+                        break;
+                    default:
+                        // put the single operand and be done
+                        putInt(sbuf, opnd, nextpc - (pc + 1));
+                        break;
+                }
+            }
+        }
+        assert (sbuf.length() == insLocs[insCount]);
+
+        return sbuf.toString();
+    }
+
+    static int getCPIndex(Element ins, char ctype,
+            ClassSyntax.GetCPIndex getCPI) {
+        int x = (int) ins.getAttrLong("ref");
+        if (x == 0 && getCPI != null) {
+            String val = ins.getAttr("val");
+            if (val == null || val.equals("")) {
+                val = ins.getText().toString();
+            }
+            byte tag;
+            switch (ctype) {
+                case 'k':
+                    tag = (byte) ins.getAttrLong("tag");
+                    break;
+                case 'c':
+                    tag = ClassSyntax.CONSTANT_Class;
+                    break;
+                case 'f':
+                    tag = ClassSyntax.CONSTANT_Fieldref;
+                    break;
+                case 'm':
+                    tag = ClassSyntax.CONSTANT_Methodref;
+                    break;
+                case 'n':
+                    tag = ClassSyntax.CONSTANT_InterfaceMethodref;
+                    break;
+                default:
+                    throw new Error("bad ctype " + ctype + " in " + ins);
+            }
+            x = getCPI.getCPIndex(tag, val);
+            //System.out.println("getCPIndex "+ins+" => "+tag+"/"+val+" => "+x);
+        } else {
+            assert (x > 0);
+        }
+        return x;
+    }
+
+    static void putInt(StringBuffer sbuf, int x, int len) {
+        //System.out.println("putInt x="+x+" len="+len);
+        boolean isSigned = false;
+        if (len < 0) {
+            len = -len;
+            isSigned = true;
+        }
+        assert (len == 1 || len == 2 || len == 4);
+        int insig = ((4 - len) * 8);  // how many insignificant bits?
+        int sx = x << insig;
+        ;<