changeset 59239:f236fd5d0c2c

8234542: code removal of Pack200 Tools and API Reviewed-by: alanb, mchung, erikj
author henryjen
date Tue, 10 Dec 2019 00:36:30 +0000
parents 2aaa8bcb90a9
children b2e191f03473
files make/autoconf/compare.sh.in make/common/Modules.gmk make/launcher/Launcher-jdk.pack.gmk make/lib/Lib-jdk.pack.gmk make/nashorn/element-list make/scripts/compare.sh make/scripts/compare_exceptions.sh.incl src/java.base/share/classes/com/sun/java/util/jar/pack/AdaptiveCoding.java src/java.base/share/classes/com/sun/java/util/jar/pack/Attribute.java src/java.base/share/classes/com/sun/java/util/jar/pack/BandStructure.java src/java.base/share/classes/com/sun/java/util/jar/pack/ClassReader.java src/java.base/share/classes/com/sun/java/util/jar/pack/ClassWriter.java src/java.base/share/classes/com/sun/java/util/jar/pack/Code.java src/java.base/share/classes/com/sun/java/util/jar/pack/Coding.java src/java.base/share/classes/com/sun/java/util/jar/pack/CodingChooser.java src/java.base/share/classes/com/sun/java/util/jar/pack/CodingMethod.java src/java.base/share/classes/com/sun/java/util/jar/pack/ConstantPool.java src/java.base/share/classes/com/sun/java/util/jar/pack/Constants.java src/java.base/share/classes/com/sun/java/util/jar/pack/Driver.java src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource.java src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource_ja.java src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource_zh_CN.java src/java.base/share/classes/com/sun/java/util/jar/pack/FixedList.java src/java.base/share/classes/com/sun/java/util/jar/pack/Fixups.java src/java.base/share/classes/com/sun/java/util/jar/pack/Histogram.java src/java.base/share/classes/com/sun/java/util/jar/pack/Instruction.java src/java.base/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java src/java.base/share/classes/com/sun/java/util/jar/pack/Package.java src/java.base/share/classes/com/sun/java/util/jar/pack/PackageReader.java src/java.base/share/classes/com/sun/java/util/jar/pack/PackageWriter.java src/java.base/share/classes/com/sun/java/util/jar/pack/PackerImpl.java src/java.base/share/classes/com/sun/java/util/jar/pack/PopulationCoding.java src/java.base/share/classes/com/sun/java/util/jar/pack/PropMap.java src/java.base/share/classes/com/sun/java/util/jar/pack/TLGlobals.java src/java.base/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java src/java.base/share/classes/com/sun/java/util/jar/pack/Utils.java src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties src/java.base/share/classes/com/sun/java/util/jar/pack/package-info.java src/java.base/share/classes/java/util/jar/Pack200.java src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java src/jdk.jartool/share/classes/sun/tools/jar/Main.java src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties src/jdk.pack/share/classes/module-info.java src/jdk.pack/share/man/pack200.1 src/jdk.pack/share/man/unpack200.1 src/jdk.pack/share/native/common-unpack/bands.cpp src/jdk.pack/share/native/common-unpack/bands.h src/jdk.pack/share/native/common-unpack/bytes.cpp src/jdk.pack/share/native/common-unpack/bytes.h src/jdk.pack/share/native/common-unpack/coding.cpp src/jdk.pack/share/native/common-unpack/coding.h src/jdk.pack/share/native/common-unpack/constants.h src/jdk.pack/share/native/common-unpack/defines.h src/jdk.pack/share/native/common-unpack/unpack.cpp src/jdk.pack/share/native/common-unpack/unpack.h src/jdk.pack/share/native/common-unpack/utils.cpp src/jdk.pack/share/native/common-unpack/utils.h src/jdk.pack/share/native/common-unpack/zip.cpp src/jdk.pack/share/native/common-unpack/zip.h src/jdk.pack/share/native/libunpack/jni.cpp src/jdk.pack/share/native/unpack200/main.cpp src/jdk.pack/windows/native/unpack200/unpack200_proto.exe.manifest src/utils/IdealGraphVisualizer/nbproject/project.properties test/jdk/ProblemList.txt test/jdk/TEST.groups test/jdk/java/util/jar/Pack200/SecurityTest.java test/jdk/tools/jar/DeprecateOptionN.java test/jdk/tools/launcher/HelpFlagsTest.java test/jdk/tools/launcher/VersionCheck.java test/jdk/tools/pack200/AttributeTests.java test/jdk/tools/pack200/BandIntegrity.java test/jdk/tools/pack200/CommandLineTests.java test/jdk/tools/pack200/DeprecatePack200.java test/jdk/tools/pack200/InstructionTests.java test/jdk/tools/pack200/ModuleAttributes.java test/jdk/tools/pack200/MultiRelease.java test/jdk/tools/pack200/Pack200Props.java test/jdk/tools/pack200/Pack200Test.java test/jdk/tools/pack200/PackChecksum.java test/jdk/tools/pack200/PackTestZip64.java test/jdk/tools/pack200/PackTestZip64Manual.java test/jdk/tools/pack200/PackageVersionTest.java test/jdk/tools/pack200/RepackTest.java test/jdk/tools/pack200/T7007157.java test/jdk/tools/pack200/TestExceptions.java test/jdk/tools/pack200/TestNormal.java test/jdk/tools/pack200/TimeStamp.java test/jdk/tools/pack200/UnpackerMemoryTest.java test/jdk/tools/pack200/Utils.java test/jdk/tools/pack200/badattr.jar test/jdk/tools/pack200/pack200-verifier/data/README test/jdk/tools/pack200/pack200-verifier/data/golden.jar test/jdk/tools/pack200/pack200-verifier/make/build.xml test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/ClassCompare.java test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/Globals.java test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/JarFileCompare.java test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/Main.java test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/VerifyTreeSet.java test/jdk/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java test/jdk/tools/pack200/pack200-verifier/src/xmlkit/CommandLineParser.java test/jdk/tools/pack200/pack200-verifier/src/xmlkit/TokenList.java test/jdk/tools/pack200/pack200-verifier/src/xmlkit/XMLKit.java test/jdk/tools/pack200/typeannos/Lambda.java test/jdk/tools/pack200/typeannos/Readme.txt test/jdk/tools/pack200/typeannos/TargetTypes.java test/jdk/tools/pack200/typeannos/TestTypeAnnotations.java test/jdk/tools/pack200/typeannos/TypeUseTarget.java
diffstat 107 files changed, 4 insertions(+), 46217 deletions(-) [+]
line wrap: on
line diff
--- a/make/autoconf/compare.sh.in	Mon Dec 09 15:28:46 2019 +0100
+++ b/make/autoconf/compare.sh.in	Tue Dec 10 00:36:30 2019 +0000
@@ -67,7 +67,6 @@
 export TAR="@TAR@"
 export TEE="@TEE@"
 export UNIQ="@UNIQ@"
-export UNPACK200="@FIXPATH@ @BOOT_JDK@/bin/unpack200"
 export UNARCHIVE="@UNZIP@ -q -o"
 
 export TOPDIR="@TOPDIR@"
--- a/make/common/Modules.gmk	Mon Dec 09 15:28:46 2019 +0100
+++ b/make/common/Modules.gmk	Tue Dec 10 00:36:30 2019 +0000
@@ -129,7 +129,6 @@
 JRE_TOOL_MODULES += \
     jdk.jdwp.agent \
     jdk.incubator.jpackage \
-    jdk.pack \
     jdk.scripting.nashorn.shell \
     #
 
@@ -170,7 +169,6 @@
     jdk.naming.dns \
     jdk.naming.rmi \
     jdk.net \
-    jdk.pack \
     jdk.rmic \
     jdk.scripting.nashorn \
     jdk.sctp \
--- a/make/launcher/Launcher-jdk.pack.gmk	Mon Dec 09 15:28:46 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-#
-# Copyright (c) 2011, 2019, 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.
-#
-
-include LauncherCommon.gmk
-
-$(eval $(call SetupBuildLauncher, pack200, \
-    MAIN_MODULE := java.base, \
-    MAIN_CLASS := com.sun.java.util.jar.pack.Driver, \
-))
-
-################################################################################
-# The order of the object files on the link command line affects the size of the resulting
-# binary (at least on linux) which causes the size to differ between old and new build.
-
-# Tell the compiler not to export any functions unless declared so in
-# the source code. On Windows, this is the default and cannot be changed.
-# On Mac, we have always exported all symbols, probably due to oversight
-# and/or misunderstanding. To emulate this, don't hide any symbols
-# by default.
-# On AIX/xlc we need at least xlc 13.1 for the symbol hiding (see JDK-8214063)
-# Also provide an override for non-conformant libraries.
-ifeq ($(TOOLCHAIN_TYPE), gcc)
-  CXXFLAGS_JDKEXE += -fvisibility=hidden
-  LDFLAGS_JDKEXE += -Wl,--exclude-libs,ALL
-else ifeq ($(TOOLCHAIN_TYPE), clang)
-  ifeq ($(call isTargetOs, macosx), false)
-    CXXFLAGS_JDKEXE += -fvisibility=hidden
-  endif
-else ifeq ($(TOOLCHAIN_TYPE), solstudio)
-  CXXFLAGS_JDKEXE += -xldscope=hidden
-endif
-
-UNPACKEXE_SRC := $(TOPDIR)/src/jdk.pack/share/native/common-unpack \
-    $(TOPDIR)/src/jdk.pack/share/native/unpack200
-UNPACKEXE_CFLAGS := -I$(TOPDIR)/src/jdk.pack/share/native/common-unpack \
-    -I$(TOPDIR)/src/java.base/share/native/libjava \
-    -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjava
-
-ifeq ($(USE_EXTERNAL_LIBZ), true)
-  UNPACKEXE_CFLAGS += -DSYSTEM_ZLIB
-  UNPACKEXE_LIBS := -lz
-else
-  UNPACKEXE_CFLAGS += -I$(TOPDIR)/src/java.base/share/native/libzip/zlib
-  UNPACKEXE_ZIPOBJS := $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/zcrc32$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/deflate$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/trees$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/zadler32$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/compress$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/zutil$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/inflate$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/infback$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/inftrees$(OBJ_SUFFIX) \
-      $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/inffast$(OBJ_SUFFIX)
-
-endif
-
-$(eval $(call SetupJdkExecutable, BUILD_UNPACKEXE, \
-    NAME := unpack200, \
-    SRC := $(UNPACKEXE_SRC), \
-    TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
-    OPTIMIZATION := LOW, \
-    CFLAGS := $(UNPACKEXE_CFLAGS) $(CXXFLAGS_JDKEXE) -DFULL, \
-    CFLAGS_release := -DPRODUCT, \
-    CFLAGS_linux := -fPIC, \
-    CFLAGS_solaris := -KPIC, \
-    CFLAGS_macosx := -fPIC, \
-    DISABLED_WARNINGS_clang := format-nonliteral, \
-    DISABLED_WARNINGS_solstudio := wunreachable, \
-    LDFLAGS := $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \
-        $(call SET_SHARED_LIBRARY_ORIGIN), \
-    LIBS := $(UNPACKEXE_LIBS) $(LIBCXX), \
-    OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpackexe, \
-    MANIFEST := $(TOPDIR)/src/jdk.pack/windows/native/unpack200/unpack200_proto.exe.manifest, \
-    MANIFEST_VERSION := $(VERSION_NUMBER_FOUR_POSITIONS), \
-    EXTRA_OBJECT_FILES := $(UNPACKEXE_ZIPOBJS) \
-))
-
-TARGETS += $(BUILD_UNPACKEXE)
-
-################################################################################
--- a/make/lib/Lib-jdk.pack.gmk	Mon Dec 09 15:28:46 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-#
-# Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  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.
-#
-
-include LibCommon.gmk
-
-################################################################################
-
-$(eval $(call SetupJdkLibrary, BUILD_LIBUNPACK, \
-    NAME := unpack, \
-    EXTRA_SRC := common-unpack, \
-    TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
-    OPTIMIZATION := LOW, \
-    CFLAGS := $(CXXFLAGS_JDKLIB) \
-        -DNO_ZLIB -DUNPACK_JNI -DFULL, \
-    CFLAGS_release := -DPRODUCT, \
-    EXTRA_HEADER_DIRS := $(call GetJavaHeaderDir, java.base), \
-    DISABLED_WARNINGS_gcc := implicit-fallthrough, \
-    DISABLED_WARNINGS_clang := format-nonliteral, \
-    DISABLED_WARNINGS_solstudio := wunreachable, \
-    LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
-        $(call SET_SHARED_LIBRARY_ORIGIN), \
-    LDFLAGS_windows := -map:$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpack.map -debug, \
-    LIBS_unix := -ljvm $(LIBCXX) -ljava, \
-    LIBS_windows := jvm.lib $(WIN_JAVA_LIB), \
-))
-
-$(BUILD_LIBUNPACK): $(call FindLib, java.base, java)
-
-TARGETS += $(BUILD_LIBUNPACK)
-
-################################################################################
--- a/make/nashorn/element-list	Mon Dec 09 15:28:46 2019 +0100
+++ b/make/nashorn/element-list	Tue Dec 10 00:36:30 2019 +0000
@@ -260,7 +260,6 @@
 module:jdk.net
 jdk.net
 jdk.nio
-module:jdk.pack
 module:jdk.rmic
 module:jdk.scripting.nashorn
 jdk.nashorn.api.scripting
--- a/make/scripts/compare.sh	Mon Dec 09 15:28:46 2019 +0100
+++ b/make/scripts/compare.sh	Tue Dec 10 00:36:30 2019 +0000
@@ -529,31 +529,6 @@
         (cd $OTHER_UNZIPDIR && $JIMAGE extract $OTHER_ZIP)
     fi
 
-    # Find all archives inside and unzip them as well to compare the contents rather than
-    # the archives. pie.jar.pack.gz i app3.war is corrupt, skip it.
-    EXCEPTIONS="pie.jar.pack.gz jdk.pack"
-    for pack in $($FIND $THIS_UNZIPDIR \( -name "*.pack" -o -name "*.pack.gz" \) -a \
-                        ! -name pie.jar.pack.gz -a ! -name jdk.pack); do
-        ($UNPACK200 $pack $pack.jar)
-        # Filter out the unzipped archives from the diff below.
-        EXCEPTIONS="$EXCEPTIONS $pack $pack.jar"
-    done
-    for pack in $($FIND $OTHER_UNZIPDIR \( -name "*.pack" -o -name "*.pack.gz" \) -a \
-                        ! -name pie.jar.pack.gz -a ! -name jdk.pack); do
-        ($UNPACK200 $pack $pack.jar)
-        EXCEPTIONS="$EXCEPTIONS $pack $pack.jar"
-    done
-    for zip in $($FIND $THIS_UNZIPDIR -name "*.jar" -o -name "*.zip"); do
-        $MKDIR $zip.unzip
-        (cd $zip.unzip && $UNARCHIVE $zip)
-        EXCEPTIONS="$EXCEPTIONS $zip"
-    done
-    for zip in $($FIND $OTHER_UNZIPDIR -name "*.jar" -o -name "*.zip"); do
-        $MKDIR $zip.unzip
-        (cd $zip.unzip && $UNARCHIVE $zip)
-        EXCEPTIONS="$EXCEPTIONS $zip"
-    done
-
     CONTENTS_DIFF_FILE=$WORK_DIR/$ZIP_FILE.diff
     # On solaris, there is no -q option.
     if [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
--- a/make/scripts/compare_exceptions.sh.incl	Mon Dec 09 15:28:46 2019 +0100
+++ b/make/scripts/compare_exceptions.sh.incl	Tue Dec 10 00:36:30 2019 +0000
@@ -50,9 +50,7 @@
   SORT_SYMBOLS="
       ./lib/libfontmanager.so
       ./lib/libjimage.so
-      ./lib/libunpack.so
       ./lib/server/libjvm.so
-      ./bin/unpack200
       ./hotspot/gtest/server/libjvm.so
       "
   KNOWN_DIS_DIFF="
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/AdaptiveCoding.java	Mon Dec 09 15:28:46 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,298 +0,0 @@
-/*
- * 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
- * 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 java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import static com.sun.java.util.jar.pack.Constants.*;
-
-/**
- * Adaptive coding.
- * See the section "Adaptive Encodings" in the Pack200 spec.
- * @author John Rose
- */
-class AdaptiveCoding implements CodingMethod {
-    CodingMethod headCoding;
-    int          headLength;
-    CodingMethod tailCoding;
-
-    public AdaptiveCoding(int headLength, CodingMethod headCoding, CodingMethod tailCoding) {
-        assert(isCodableLength(headLength));
-        this.headLength = headLength;
-        this.headCoding = headCoding;
-        this.tailCoding = tailCoding;
-    }
-
-    public void setHeadCoding(CodingMethod headCoding) {
-        this.headCoding = headCoding;
-    }
-    public void setHeadLength(int headLength) {
-        assert(isCodableLength(headLength));
-        this.headLength = headLength;
-    }
-    public void setTailCoding(CodingMethod tailCoding) {
-        this.tailCoding = tailCoding;
-    }
-
-    public boolean isTrivial() {
-        return headCoding == tailCoding;
-    }
-
-    // CodingMethod methods.
-    public void writeArrayTo(OutputStream out, int[] a, int start, int end) throws IOException {
-        writeArray(this, out, a, start, end);
-    }
-    // writeArrayTo must be coded iteratively, not recursively:
-    private static void writeArray(AdaptiveCoding run, OutputStream out, int[] a, int start, int end) throws IOException {
-        for (;;) {
-            int mid = start+run.headLength;
-            assert(mid <= end);
-            run.headCoding.writeArrayTo(out, a, start, mid);
-            start = mid;
-            if (run.tailCoding instanceof AdaptiveCoding) {
-                run = (AdaptiveCoding) run.tailCoding;
-                continue;
-            }
-            break;
-        }
-        run.tailCoding.writeArrayTo(out, a, start, end);
-    }
-
-    public void readArrayFrom(InputStream in, int[] a, int start, int end) throws IOException {
-        readArray(this, in, a, start, end);
-    }
-    private static void readArray(AdaptiveCoding run, InputStream in, int[] a, int start, int end) throws IOException {
-        for (;;) {
-            int mid = start+run.headLength;
-            assert(mid <= end);
-            run.headCoding.readArrayFrom(in, a, start, mid);
-            start = mid;
-            if (run.tailCoding instanceof AdaptiveCoding) {
-                run = (AdaptiveCoding) run.tailCoding;
-                continue;
-            }
-            break;
-        }
-        run.tailCoding.readArrayFrom(in, a, start, end);
-    }
-
-    public static final int KX_MIN = 0;
-    public static final int KX_MAX = 3;
-    public static final int KX_LG2BASE = 4;
-    public static final int KX_BASE = 16;
-
-    public static final int KB_MIN = 0x00;
-    public static final int KB_MAX = 0xFF;
-    public static final int KB_OFFSET = 1;
-    public static final int KB_DEFAULT = 3;
-
-    static int getKXOf(int K) {
-        for (int KX = KX_MIN; KX <= KX_MAX; KX++) {
-            if (((K - KB_OFFSET) & ~KB_MAX) == 0)
-                return KX;
-            K >>>= KX_LG2BASE;
-        }
-        return -1;
-    }
-
-    static int getKBOf(int K) {
-        int KX = getKXOf(K);
-        if (KX < 0)  return -1;
-        K >>>= (KX * KX_LG2BASE);
-        return K-1;
-    }
-
-    static int decodeK(int KX, int KB) {
-        assert(KX_MIN <= KX && KX <= KX_MAX);
-        assert(KB_MIN <= KB && KB <= KB_MAX);
-        return (KB+KB_OFFSET) << (KX * KX_LG2BASE);
-    }
-
-    static int getNextK(int K) {
-        if (K <= 0)  return 1;  // 1st K value
-        int KX = getKXOf(K);
-        if (KX < 0)  return Integer.MAX_VALUE;
-        // This is the increment we expect to apply:
-        int unit = 1      << (KX * KX_LG2BASE);
-        int mask = KB_MAX << (KX * KX_LG2BASE);
-        int K1 = K + unit;
-        K1 &= ~(unit-1);  // cut off stray low-order bits
-        if (((K1 - unit) & ~mask) == 0) {
-            assert(getKXOf(K1) == KX);
-            return K1;
-        }
-        if (KX == KX_MAX)  return Integer.MAX_VALUE;
-        KX += 1;
-        int mask2 = KB_MAX << (KX * KX_LG2BASE);
-        K1 |= (mask & ~mask2);
-        K1 += unit;
-        assert(getKXOf(K1) == KX);
-        return K1;
-    }
-
-    // Is K of the form ((KB:[0..255])+1) * 16^(KX:{0..3])?
-    public static boolean isCodableLength(int K) {
-        int KX = getKXOf(K);
-        if (KX < 0)  return false;
-        int unit = 1      << (KX * KX_LG2BASE);
-        int mask = KB_MAX << (KX * KX_LG2BASE);
-        return ((K - unit) & ~mask) == 0;
-    }
-
-    public byte[] getMetaCoding(Coding dflt) {
-        //assert(!isTrivial()); // can happen
-        // See the isCodableLength restriction in CodingChooser.
-        ByteArrayOutputStream bytes = new ByteArrayOutputStream(10);
-        try {
-            makeMetaCoding(this, dflt, bytes);
-        } catch (IOException ee) {
-            throw new RuntimeException(ee);
-        }
-        return bytes.toByteArray();
-    }
-    private static void makeMetaCoding(AdaptiveCoding run, Coding dflt,
-                                       ByteArrayOutputStream bytes)
-                                      throws IOException {
-        for (;;) {
-            CodingMethod headCoding = run.headCoding;
-            int          headLength = run.headLength;
-            CodingMethod tailCoding = run.tailCoding;
-            int K = headLength;
-            assert(isCodableLength(K));
-            int ADef   = (headCoding == dflt)?1:0;
-            int BDef   = (tailCoding == dflt)?1:0;
-            if (ADef+BDef > 1)  BDef = 0;  // arbitrary choice
-            int ABDef  = 1*ADef + 2*BDef;
-            assert(ABDef < 3);
-            int KX     = getKXOf(K);
-            int KB     = getKBOf(K);
-            assert(decodeK(KX, KB) == K);
-            int KBFlag = (KB != KB_DEFAULT)?1:0;
-            bytes.write(_meta_run + KX + 4*KBFlag + 8*ABDef);
-            if (KBFlag != 0)    bytes.write(KB);
-            if (ADef == 0)  bytes.write(headCoding.getMetaCoding(dflt));
-            if (tailCoding instanceof AdaptiveCoding) {
-                run = (AdaptiveCoding) tailCoding;
-                continue; // tail call, to avoid deep stack recursion
-            }
-            if (BDef == 0)  bytes.write(tailCoding.getMetaCoding(dflt));
-            break;
-        }
-    }
-    public static int parseMetaCoding(byte[] bytes, int pos, Coding dflt, CodingMethod res[]) {
-        int op = bytes[pos++] & 0xFF;
-        if (op < _meta_run || op >= _meta_pop)  return pos-1; // backup
-        AdaptiveCoding prevc = null;
-        for (boolean keepGoing = true; keepGoing; ) {
-            keepGoing = false;
-            assert(op >= _meta_run);
-            op -= _meta_run;
-            int KX = op % 4;
-            int KBFlag = (op / 4) % 2;
-            int ABDef = (op / 8);
-            assert(ABDef < 3);
-            int ADef = (ABDef & 1);
-            int BDef = (ABDef & 2);
-            CodingMethod[] ACode = {dflt}, BCode = {dflt};
-            int KB = KB_DEFAULT;
-            if (KBFlag != 0)
-                KB = bytes[pos++] & 0xFF;
-            if (ADef == 0) {
-                pos = BandStructure.parseMetaCoding(bytes, pos, dflt, ACode);
-            }
-            if (BDef == 0 &&
-                ((op = bytes[pos] & 0xFF) >= _meta_run) && op < _meta_pop) {
-                pos++;
-                keepGoing = true;
-            } else if (BDef == 0) {
-                pos = BandStructure.parseMetaCoding(bytes, pos, dflt, BCode);
-            }
-            AdaptiveCoding newc = new AdaptiveCoding(decodeK(KX, KB),
-                                                     ACode[0], BCode[0]);
-            if (prevc == null) {
-                res[0] = newc;
-            } else {
-                prevc.tailCoding = newc;
-            }
-            prevc = newc;
-        }
-        return pos;
-    }
-
-    private String keyString(CodingMethod m) {
-        if (m instanceof Coding)
-            return ((Coding)m).keyString();
-        return m.toString();
-    }
-    public String toString() {
-        StringBuilder res = new StringBuilder(20);
-        AdaptiveCoding run = this;
-        res.append("run(");
-        for (;;) {
-            res.append(run.headLength).append("*");
-            res.append(keyString(run.headCoding));
-            if (run.tailCoding instanceof AdaptiveCoding) {
-                run = (AdaptiveCoding) run.tailCoding;
-                res.append(" ");
-                continue;
-            }
-            break;
-        }
-        res.append(" **").append(keyString(run.tailCoding));
-        res.append(")");
-        return res.toString();
-    }
-
-/*
-    public static void main(String av[]) {
-        int[][] samples = {
-            {1,2,3,4,5},
-            {254,255,256,256+1*16,256+2*16},
-            {0xfd,0xfe,0xff,0x100,0x110,0x120,0x130},
-            {0xfd0,0xfe0,0xff0,0x1000,0x1100,0x1200,0x1300},
-            {0xfd00,0xfe00,0xff00,0x10000,0x11000,0x12000,0x13000},
-            {0xfd000,0xfe000,0xff000,0x100000}
-        };
-        for (int i = 0; i < samples.length; i++) {
-            for (int j = 0; j < samples[i].length; j++) {
-                int K = samples[i][j];
-                int KX = getKXOf(K);
-                int KB = getKBOf(K);
-                System.out.println("K="+Integer.toHexString(K)+
-                                   " KX="+KX+" KB="+KB);
-                assert(isCodableLength(K));
-                assert(K == decodeK(KX, KB));
-                if (j == 0)  continue;
-                int K1 = samples[i][j-1];
-                assert(K == getNextK(K1));
-            }
-        }
-    }
-//*/
-
-}
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/Attribute.java	Mon Dec 09 15:28:46 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1699 +0,0 @@
-/*
- * Copyright (c) 2003, 2019, 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.Entry;
-import com.sun.java.util.jar.pack.ConstantPool.Index;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import static com.sun.java.util.jar.pack.Constants.*;
-
-/**
- * Represents an attribute in a class-file.
- * Takes care to remember where constant pool indexes occur.
- * Implements the "little language" of Pack200 for describing
- * attribute layouts.
- * @author John Rose
- */
-class Attribute implements Comparable<Attribute> {
-    // Attribute instance fields.
-
-    Layout def;     // the name and format of this attr
-    byte[] bytes;   // the actual bytes
-    Object fixups;  // reference relocations, if any are required
-
-    public String name() { return def.name(); }
-    public Layout layout() { return def; }
-    public byte[] bytes() { return bytes; }
-    public int size() { return bytes.length; }
-    public Entry getNameRef() { return def.getNameRef(); }
-
-    private Attribute(Attribute old) {
-        this.def = old.def;
-        this.bytes = old.bytes;
-        this.fixups = old.fixups;
-    }
-
-    public Attribute(Layout def, byte[] bytes, Object fixups) {
-        this.def = def;
-        this.bytes = bytes;
-        this.fixups = fixups;
-        Fixups.setBytes(fixups, bytes);
-    }
-    public Attribute(Layout def, byte[] bytes) {
-        this(def, bytes, null);
-    }
-
-    public Attribute addContent(byte[] bytes, Object fixups) {
-        assert(isCanonical());
-        if (bytes.length == 0 && fixups == null)
-            return this;
-        Attribute res = new Attribute(this);
-        res.bytes = bytes;
-        res.fixups = fixups;
-        Fixups.setBytes(fixups, bytes);
-        return res;
-    }
-    public Attribute addContent(byte[] bytes) {
-        return addContent(bytes, null);
-    }
-
-    public void finishRefs(Index ix) {
-        if (fixups != null) {
-            Fixups.finishRefs(fixups, bytes, ix);
-            fixups = null;
-        }
-    }
-
-    public boolean isCanonical() {
-        return this == def.canon;
-    }
-
-    @Override
-    public int compareTo(Attribute that) {
-        return this.def.compareTo(that.def);
-    }
-
-    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<Attribute> getCanonList(List<Attribute> al) {
-        synchronized (canonLists) {
-            List<Attribute> cl = canonLists.get(al);
-            if (cl == null) {
-                cl = new ArrayList<>(al.size());
-                cl.addAll(al);
-                cl = Collections.unmodifiableList(cl);
-                canonLists.put(al, cl);
-            }
-            return cl;
-        }
-    }
-
-    // Find the canonical empty attribute with the given ctype, name, layout.
-    public static Attribute find(int ctype, String name, String layout) {
-        Layout key = Layout.makeKey(ctype, name, layout);
-        synchronized (attributes) {
-            Attribute a = attributes.get(key);
-            if (a == null) {
-                a = new Layout(ctype, name, layout).canonicalInstance();
-                attributes.put(key, a);
-            }
-            return a;
-        }
-    }
-
-    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<Layout, Attribute> defs, int ctype,
-            String name) {
-        if (defs == null) {
-            defs = standardDefs;
-        }
-        return defs.get(Layout.makeKey(ctype, name));
-    }
-
-    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<Layout, Attribute> sd = standardDefs;
-        define(sd, ATTR_CONTEXT_CLASS, "Signature", "RSH");
-        define(sd, ATTR_CONTEXT_CLASS, "Synthetic", "");
-        define(sd, ATTR_CONTEXT_CLASS, "Deprecated", "");
-        define(sd, ATTR_CONTEXT_CLASS, "SourceFile", "RUH");
-        define(sd, ATTR_CONTEXT_CLASS, "EnclosingMethod", "RCHRDNH");
-        define(sd, ATTR_CONTEXT_CLASS, "InnerClasses", "NH[RCHRCNHRUNHFH]");
-        define(sd, ATTR_CONTEXT_CLASS, "BootstrapMethods", "NH[RMHNH[KLH]]");
-
-        define(sd, ATTR_CONTEXT_FIELD, "Signature", "RSH");
-        define(sd, ATTR_CONTEXT_FIELD, "Synthetic", "");
-        define(sd, ATTR_CONTEXT_FIELD, "Deprecated", "");
-        define(sd, ATTR_CONTEXT_FIELD, "ConstantValue", "KQH");
-
-        define(sd, ATTR_CONTEXT_METHOD, "Signature", "RSH");
-        define(sd, ATTR_CONTEXT_METHOD, "Synthetic", "");
-        define(sd, ATTR_CONTEXT_METHOD, "Deprecated", "");
-        define(sd, ATTR_CONTEXT_METHOD, "Exceptions", "NH[RCH]");
-        define(sd, ATTR_CONTEXT_METHOD, "MethodParameters", "NB[RUNHFH]");
-        //define(sd, ATTR_CONTEXT_METHOD, "Code", "HHNI[B]NH[PHPOHPOHRCNH]NH[RUHNI[B]]");
-
-        define(sd, ATTR_CONTEXT_CODE, "StackMapTable",
-               ("[NH[(1)]]" +
-                "[TB" +
-                "(64-127)[(2)]" +
-                "(247)[(1)(2)]" +
-                "(248-251)[(1)]" +
-                "(252)[(1)(2)]" +
-                "(253)[(1)(2)(2)]" +
-                "(254)[(1)(2)(2)(2)]" +
-                "(255)[(1)NH[(2)]NH[(2)]]" +
-                "()[]" +
-                "]" +
-                "[H]" +
-                "[TB(7)[RCH](8)[PH]()[]]"));
-
-        define(sd, ATTR_CONTEXT_CODE, "LineNumberTable", "NH[PHH]");
-        define(sd, ATTR_CONTEXT_CODE, "LocalVariableTable", "NH[PHOHRUHRSHH]");
-        define(sd, ATTR_CONTEXT_CODE, "LocalVariableTypeTable", "NH[PHOHRUHRSHH]");
-        //define(sd, ATTR_CONTEXT_CODE, "CharacterRangeTable", "NH[PHPOHIIH]");
-        //define(sd, ATTR_CONTEXT_CODE, "CoverageTable", "NH[PHHII]");
-
-        // Note:  Code and InnerClasses are special-cased elsewhere.
-        // Their layout specs. are given here for completeness.
-        // The Code spec is incomplete, in that it does not distinguish
-        // bytecode bytes or locate CP references.
-        // The BootstrapMethods attribute is also special-cased
-        // elsewhere as an appendix to the local constant pool.
-    }
-
-    // Metadata.
-    //
-    // We define metadata using similar layouts
-    // for all five kinds of metadata attributes and 2 type metadata attributes
-    //
-    // Regular annotations are a counted list of [RSHNH[RUH(1)]][...]
-    //   pack.method.attribute.RuntimeVisibleAnnotations=[NH[(1)]][RSHNH[RUH(1)]][TB...]
-    //
-    // Parameter annotations are a counted list of regular annotations.
-    //   pack.method.attribute.RuntimeVisibleParameterAnnotations=[NB[(1)]][NH[(1)]][RSHNH[RUH(1)]][TB...]
-    //
-    // RuntimeInvisible annotations are defined similarly...
-    // Non-method annotations are defined similarly...
-    //
-    // Annotation are a simple tagged value [TB...]
-    //   pack.attribute.method.AnnotationDefault=[TB...]
-
-    static {
-        String mdLayouts[] = {
-            Attribute.normalizeLayoutString
-            (""
-             +"\n  # parameter_annotations :="
-             +"\n  [ NB[(1)] ]     # forward call to annotations"
-             ),
-            Attribute.normalizeLayoutString
-            (""
-             +"\n  # annotations :="
-             +"\n  [ NH[(1)] ]     # forward call to annotation"
-             +"\n  "
-            ),
-            Attribute.normalizeLayoutString
-             (""
-             +"\n  # annotation :="
-             +"\n  [RSH"
-             +"\n    NH[RUH (1)]   # forward call to value"
-             +"\n    ]"
-             ),
-            Attribute.normalizeLayoutString
-            (""
-             +"\n  # value :="
-             +"\n  [TB # Callable 2 encodes one tagged value."
-             +"\n    (\\B,\\C,\\I,\\S,\\Z)[KIH]"
-             +"\n    (\\D)[KDH]"
-             +"\n    (\\F)[KFH]"
-             +"\n    (\\J)[KJH]"
-             +"\n    (\\c)[RSH]"
-             +"\n    (\\e)[RSH RUH]"
-             +"\n    (\\s)[RUH]"
-             +"\n    (\\[)[NH[(0)]] # backward self-call to value"
-             +"\n    (\\@)[RSH NH[RUH (0)]] # backward self-call to value"
-             +"\n    ()[] ]"
-             )
-        };
-        /*
-         * RuntimeVisibleTypeAnnotation and RuntimeInvisibleTypeAnnotatation are
-         * similar to RuntimeVisibleAnnotation and RuntimeInvisibleAnnotation,
-         * a type-annotation union  and a type-path structure precedes the
-         * annotation structure
-         */
-        String typeLayouts[] = {
-            Attribute.normalizeLayoutString
-            (""
-             +"\n # type-annotations :="
-             +"\n  [ NH[(1)(2)(3)] ]     # forward call to type-annotations"
-            ),
-            Attribute.normalizeLayoutString
-            ( ""
-             +"\n  # type-annotation :="
-             +"\n  [TB"
-             +"\n    (0-1) [B] # {CLASS, METHOD}_TYPE_PARAMETER"
-             +"\n    (16) [FH] # CLASS_EXTENDS"
-             +"\n    (17-18) [BB] # {CLASS, METHOD}_TYPE_PARAMETER_BOUND"
-             +"\n    (19-21) [] # FIELD, METHOD_RETURN, METHOD_RECEIVER"
-             +"\n    (22) [B] # METHOD_FORMAL_PARAMETER"
-             +"\n    (23) [H] # THROWS"
-             +"\n    (64-65) [NH[PHOHH]] # LOCAL_VARIABLE, RESOURCE_VARIABLE"
-             +"\n    (66) [H] # EXCEPTION_PARAMETER"
-             +"\n    (67-70) [PH] # INSTANCEOF, NEW, {CONSTRUCTOR, METHOD}_REFERENCE_RECEIVER"
-             +"\n    (71-75) [PHB] # CAST, {CONSTRUCTOR,METHOD}_INVOCATION_TYPE_ARGUMENT, {CONSTRUCTOR, METHOD}_REFERENCE_TYPE_ARGUMENT"
-             +"\n    ()[] ]"
-            ),
-            Attribute.normalizeLayoutString
-            (""
-             +"\n # type-path"
-             +"\n [ NB[BB] ]"
-            )
-        };
-        Map<Layout, Attribute> sd = standardDefs;
-        String defaultLayout     = mdLayouts[3];
-        String annotationsLayout = mdLayouts[1] + mdLayouts[2] + mdLayouts[3];
-        String paramsLayout      = mdLayouts[0] + annotationsLayout;
-        String typesLayout       = typeLayouts[0] + typeLayouts[1] +
-                                   typeLayouts[2] + mdLayouts[2] + mdLayouts[3];
-
-        for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) {
-            if (ctype != ATTR_CONTEXT_CODE) {
-                define(sd, ctype,
-                       "RuntimeVisibleAnnotations",   annotationsLayout);
-                define(sd, ctype,
-                       "RuntimeInvisibleAnnotations",  annotationsLayout);
-
-                if (ctype == ATTR_CONTEXT_METHOD) {
-                    define(sd, ctype,
-                           "RuntimeVisibleParameterAnnotations",   paramsLayout);
-                    define(sd, ctype,
-                           "RuntimeInvisibleParameterAnnotations", paramsLayout);
-                    define(sd, ctype,
-                           "AnnotationDefault", defaultLayout);
-                }
-            }
-            define(sd, ctype,
-                   "RuntimeVisibleTypeAnnotations", typesLayout);
-            define(sd, ctype,
-                   "RuntimeInvisibleTypeAnnotations", typesLayout);
-        }
-    }
-
-    public static String contextName(int ctype) {
-        switch (ctype) {
-        case ATTR_CONTEXT_CLASS: return "class";
-        case ATTR_CONTEXT_FIELD: return "field";
-        case ATTR_CONTEXT_METHOD: return "method";
-        case ATTR_CONTEXT_CODE: return "code";
-        }
-        return null;
-    }
-
-    /** 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
-     *  bits and attribute indicators.
-     */
-    public abstract static
-    class Holder {
-
-        // We need this abstract method to interpret embedded CP refs.
-        protected abstract Entry[] getCPMap();
-
-        protected int flags;             // defined here for convenience
-        protected List<Attribute> attributes;
-
-        public int attributeSize() {
-            return (attributes == null) ? 0 : attributes.size();
-        }
-
-        public void trimToSize() {
-            if (attributes == null) {
-                return;
-            }
-            if (attributes.isEmpty()) {
-                attributes = null;
-                return;
-            }
-            if (attributes instanceof ArrayList) {
-                ArrayList<Attribute> al = (ArrayList<Attribute>)attributes;
-                al.trimToSize();
-                boolean allCanon = true;
-                for (Attribute a : al) {
-                    if (!a.isCanonical()) {
-                        allCanon = false;
-                    }
-                    if (a.fixups != null) {
-                        assert(!a.isCanonical());
-                        a.fixups = Fixups.trimToSize(a.fixups);
-                    }
-                }
-                if (allCanon) {
-                    // Replace private writable attribute list
-                    // with only trivial entries by public unique
-                    // immutable attribute list with the same entries.
-                    attributes = getCanonList(al);
-                }
-            }
-        }
-
-        public void addAttribute(Attribute a) {
-            if (attributes == null)
-                attributes = new ArrayList<>(3);
-            else if (!(attributes instanceof ArrayList))
-                attributes = new ArrayList<>(attributes);  // unfreeze it
-            attributes.add(a);
-        }
-
-        public Attribute removeAttribute(Attribute a) {
-            if (attributes == null)       return null;
-            if (!attributes.contains(a))  return null;
-            if (!(attributes instanceof ArrayList))
-                attributes = new ArrayList<>(attributes);  // unfreeze it
-            attributes.remove(a);
-            return a;
-        }
-
-        public Attribute getAttribute(int n) {
-            return attributes.get(n);
-        }
-
-        protected void visitRefs(int mode, Collection<Entry> refs) {
-            if (attributes == null)  return;
-            for (Attribute a : attributes) {
-                a.visitRefs(this, mode, refs);
-            }
-        }
-
-        static final List<Attribute> noAttributes = Arrays.asList(new Attribute[0]);
-
-        public List<Attribute> getAttributes() {
-            if (attributes == null)
-                return noAttributes;
-            return attributes;
-        }
-
-        public void setAttributes(List<Attribute> attrList) {
-            if (attrList.isEmpty())
-                attributes = null;
-            else
-                attributes = attrList;
-        }
-
-        public Attribute getAttribute(String attrName) {
-            if (attributes == null)  return null;
-            for (Attribute a : attributes) {
-                if (a.name().equals(attrName))
-                    return a;
-            }
-            return null;
-        }
-
-        public Attribute getAttribute(Layout attrDef) {
-            if (attributes == null)  return null;
-            for (Attribute a : attributes) {
-                if (a.layout() == attrDef)
-                    return a;
-            }
-            return null;
-        }
-
-        public Attribute removeAttribute(String attrName) {
-            return removeAttribute(getAttribute(attrName));
-        }
-
-        public Attribute removeAttribute(Layout attrDef) {
-            return removeAttribute(getAttribute(attrDef));
-        }
-
-        public void strip(String attrName) {
-            removeAttribute(getAttribute(attrName));
-        }
-    }
-
-    // Lightweight interface to hide details of band structure.
-    // Also used for testing.
-    public abstract static
-    class ValueStream {
-        public int getInt(int bandIndex) { throw undef(); }
-        public void putInt(int bandIndex, int value) { throw undef(); }
-        public Entry getRef(int bandIndex) { throw undef(); }
-        public void putRef(int bandIndex, Entry ref) { throw undef(); }
-        // Note:  decodeBCI goes w/ getInt/Ref; encodeBCI goes w/ putInt/Ref
-        public int decodeBCI(int bciCode) { throw undef(); }
-        public int encodeBCI(int bci) { throw undef(); }
-        public void noteBackCall(int whichCallable) { /* ignore by default */ }
-        private RuntimeException undef() {
-            return new UnsupportedOperationException("ValueStream method");
-        }
-    }
-
-    // Element kinds:
-    static final byte EK_INT  = 1;     // B H I SH etc.
-    static final byte EK_BCI  = 2;     // PH POH etc.
-    static final byte EK_BCO  = 3;     // OH etc.
-    static final byte EK_FLAG = 4;     // FH etc.
-    static final byte EK_REPL = 5;     // NH[...] etc.
-    static final byte EK_REF  = 6;     // RUH, RUNH, KQH, etc.
-    static final byte EK_UN   = 7;     // TB(...)[...] etc.
-    static final byte EK_CASE = 8;     // (...)[...] etc.
-    static final byte EK_CALL = 9;     // (0), (1), etc.
-    static final byte EK_CBLE = 10;    // [...][...] etc.
-    static final byte EF_SIGN  = 1<<0;   // INT is signed
-    static final byte EF_DELTA = 1<<1;   // BCI/BCI value is diff'ed w/ previous
-    static final byte EF_NULL  = 1<<2;   // null REF is expected/allowed
-    static final byte EF_BACK  = 1<<3;   // call, callable, case is backward
-    static final int NO_BAND_INDEX = -1;
-
-    /** A "class" of attributes, characterized by a context-type, name
-     *  and format.  The formats are specified in a "little language".
-     */
-    public static
-    class Layout implements Comparable<Layout> {
-        int ctype;       // attribute context type, e.g., ATTR_CONTEXT_CODE
-        String name;     // name of attribute
-        boolean hasRefs; // this kind of attr contains CP refs?
-        String layout;   // layout specification
-        int bandCount;   // total number of elems
-        Element[] elems; // tokenization of layout
-        Attribute canon; // canonical instance of this layout
-
-        public int ctype() { return ctype; }
-        public String name() { return name; }
-        public String layout() { return layout; }
-        public Attribute canonicalInstance() { return canon; }
-
-        public Entry getNameRef() {
-            return ConstantPool.getUtf8Entry(name());
-        }
-
-        public boolean isEmpty() {
-            return layout.isEmpty();
-        }
-
-        public Layout(int ctype, String name, String layout) {
-            this.ctype = ctype;
-            this.name = name.intern();
-            this.layout = layout.intern();
-            assert(ctype < ATTR_CONTEXT_LIMIT);
-            boolean hasCallables = layout.startsWith("[");
-            try {
-                if (!hasCallables) {
-                    this.elems = tokenizeLayout(this, -1, layout);
-                } else {
-                    String[] bodies = splitBodies(layout);
-                    // Make the callables now, so they can be linked immediately.
-                    Element[] lelems = new Element[bodies.length];
-                    this.elems = lelems;
-                    for (int i = 0; i < lelems.length; i++) {
-                        Element ce = this.new Element();
-                        ce.kind = EK_CBLE;
-                        ce.removeBand();
-                        ce.bandIndex = NO_BAND_INDEX;
-                        ce.layout = bodies[i];
-                        lelems[i] = ce;
-                    }
-                    // Next fill them in.
-                    for (int i = 0; i < lelems.length; i++) {
-                        Element ce = lelems[i];
-                        ce.body = tokenizeLayout(this, i, bodies[i]);
-                    }
-                    //System.out.println(Arrays.asList(elems));
-                }
-            } catch (StringIndexOutOfBoundsException ee) {
-                // simplest way to catch syntax errors...
-                throw new RuntimeException("Bad attribute layout: "+layout, ee);
-            }
-            // Some uses do not make a fresh one for each occurrence.
-            // For example, if layout == "", we only need one attr to share.
-            canon = new Attribute(this, noBytes);
-        }
-        private Layout() {}
-        static Layout makeKey(int ctype, String name, String layout) {
-            Layout def = new Layout();
-            def.ctype = ctype;
-            def.name = name.intern();
-            def.layout = layout.intern();
-            assert(ctype < ATTR_CONTEXT_LIMIT);
-            return def;
-        }
-        static Layout makeKey(int ctype, String name) {
-            return makeKey(ctype, name, "");
-        }
-
-        public Attribute addContent(byte[] bytes, Object fixups) {
-            return canon.addContent(bytes, fixups);
-        }
-        public Attribute addContent(byte[] bytes) {
-            return canon.addContent(bytes, null);
-        }
-
-        @Override
-        public boolean equals(Object x) {
-            return ( x != null) && ( x.getClass() == Layout.class ) &&
-                    equals((Layout)x);
-        }
-        public boolean equals(Layout that) {
-            return this.name.equals(that.name)
-                && this.layout.equals(that.layout)
-                && this.ctype == that.ctype;
-        }
-        @Override
-        public int hashCode() {
-            return (((17 + name.hashCode())
-                    * 37 + layout.hashCode())
-                    * 37 + ctype);
-        }
-        @Override
-        public int compareTo(Layout that) {
-            int r;
-            r = this.name.compareTo(that.name);
-            if (r != 0)  return r;
-            r = this.layout.compareTo(that.layout);
-            if (r != 0)  return r;
-            return this.ctype - that.ctype;
-        }
-        @Override
-        public String toString() {
-            String str = contextName(ctype)+"."+name+"["+layout+"]";
-            // If -ea, print out more informative strings!
-            assert((str = stringForDebug()) != null);
-            return str;
-        }
-        private String stringForDebug() {
-            return contextName(ctype)+"."+name+Arrays.asList(elems);
-        }
-
-        public
-        class Element {
-            String layout;   // spelling in the little language
-            byte flags;      // EF_SIGN, etc.
-            byte kind;       // EK_UINT, etc.
-            byte len;        // scalar length of element
-            byte refKind;    // CONSTANT_String, etc.
-            int bandIndex;   // which band does this element govern?
-            int value;       // extra parameter
-            Element[] body;  // extra data (for replications, unions, calls)
-
-            boolean flagTest(byte mask) { return (flags & mask) != 0; }
-
-            Element() {
-                bandIndex = bandCount++;
-            }
-
-            void removeBand() {
-                --bandCount;
-                assert(bandIndex == bandCount);
-                bandIndex = NO_BAND_INDEX;
-            }
-
-            public boolean hasBand() {
-                return bandIndex >= 0;
-            }
-            public String toString() {
-                String str = layout;
-                // If -ea, print out more informative strings!
-                assert((str = stringForDebug()) != null);
-                return str;
-            }
-            private String stringForDebug() {
-                Element[] lbody = this.body;
-                switch (kind) {
-                case EK_CALL:
-                    lbody = null;
-                    break;
-                case EK_CASE:
-                    if (flagTest(EF_BACK))
-                        lbody = null;
-                    break;
-                }
-                return layout
-                    + (!hasBand()?"":"#"+bandIndex)
-                    + "<"+ (flags==0?"":""+flags)+kind+len
-                    + (refKind==0?"":""+refKind) + ">"
-                    + (value==0?"":"("+value+")")
-                    + (lbody==null?"": ""+Arrays.asList(lbody));
-            }
-        }
-
-        public boolean hasCallables() {
-            return (elems.length > 0 && elems[0].kind == EK_CBLE);
-        }
-        private static final Element[] noElems = {};
-        public Element[] getCallables() {
-            if (hasCallables()) {
-                Element[] nelems = Arrays.copyOf(elems, elems.length);
-                return nelems;
-            } else
-                return noElems;  // no callables at all
-        }
-        public Element[] getEntryPoint() {
-            if (hasCallables())
-                return elems[0].body;  // body of first callable
-            else {
-                Element[] nelems = Arrays.copyOf(elems, elems.length);
-                return nelems;  // no callables; whole body
-            }
-        }
-
-        /** Return a sequence of tokens from the given attribute bytes.
-         *  Sequence elements will be 1-1 correspondent with my layout tokens.
-         */
-        public void parse(Holder holder,
-                          byte[] bytes, int pos, int len, ValueStream out) {
-            int end = parseUsing(getEntryPoint(),
-                                 holder, bytes, pos, len, out);
-            if (end != pos + len)
-                throw new InternalError("layout parsed "+(end-pos)+" out of "+len+" bytes");
-        }
-        /** Given a sequence of tokens, return the attribute bytes.
-         *  Sequence elements must be 1-1 correspondent with my layout tokens.
-         *  The returned object is a cookie for Fixups.finishRefs, which
-         *  must be used to harden any references into integer indexes.
-         */
-        public Object unparse(ValueStream in, ByteArrayOutputStream out) {
-            Object[] fixups = { null };
-            unparseUsing(getEntryPoint(), fixups, in, out);
-            return fixups[0]; // return ref-bearing cookie, if any
-        }
-
-        public String layoutForClassVersion(Package.Version vers) {
-            if (vers.lessThan(JAVA6_MAX_CLASS_VERSION)) {
-                // Disallow layout syntax in the oldest protocol version.
-                return expandCaseDashNotation(layout);
-            }
-            return layout;
-        }
-    }
-
-    public static
-    class FormatException extends IOException {
-        @java.io.Serial
-        private static final long serialVersionUID = -2542243830788066513L;
-
-        private int ctype;
-        private String name;
-        String layout;
-        public FormatException(String message,
-                               int ctype, String name, String layout) {
-            super(ATTR_CONTEXT_NAME[ctype]+ " attribute \"" + name + "\"" +
-                  (message == null? "" : (": " + message)));
-            this.ctype = ctype;
-            this.name = name;
-            this.layout = layout;
-        }
-        public FormatException(String message,
-                               int ctype, String name) {
-            this(message, ctype, name, null);
-        }
-    }
-
-    void visitRefs(Holder holder, int mode, final Collection<Entry> refs) {
-        if (mode == VRM_CLASSIC) {
-            refs.add(getNameRef());
-        }
-        // else the name is owned by the layout, and is processed elsewhere
-        if (bytes.length == 0)  return;  // quick exit
-        if (!def.hasRefs)       return;  // quick exit
-        if (fixups != null) {
-            Fixups.visitRefs(fixups, refs);
-            return;
-        }
-        // References (to a local cpMap) are embedded in the bytes.
-        def.parse(holder, bytes, 0, bytes.length,
-            new ValueStream() {
-                @Override
-                public void putInt(int bandIndex, int value) {
-                }
-                @Override
-                public void putRef(int bandIndex, Entry ref) {
-                    refs.add(ref);
-                }
-                @Override
-                public int encodeBCI(int bci) {
-                    return bci;
-                }
-            });
-    }
-
-    public void parse(Holder holder, byte[] bytes, int pos, int len, ValueStream out) {
-        def.parse(holder, bytes, pos, len, out);
-    }
-    public Object unparse(ValueStream in, ByteArrayOutputStream out) {
-        return def.unparse(in, out);
-    }
-
-    @Override
-    public String toString() {
-        return def
-            +"{"+(bytes == null ? -1 : size())+"}"
-            +(fixups == null? "": fixups.toString());
-    }
-
-    /** Remove any informal "pretty printing" from the layout string.
-     *  Removes blanks and control chars.
-     *  Removes '#' comments (to end of line).
-     *  Replaces '\c' by the decimal code of the character c.
-     *  Replaces '0xNNN' by the decimal code of the hex number NNN.
-     */
-    public static
-    String normalizeLayoutString(String layout) {
-        StringBuilder buf = new StringBuilder();
-        for (int i = 0, len = layout.length(); i < len; ) {
-            char ch = layout.charAt(i++);
-            if (ch <= ' ') {
-                // Skip whitespace and control chars
-                continue;
-            } else if (ch == '#') {
-                // Skip to end of line.
-                int end1 = layout.indexOf('\n', i);
-                int end2 = layout.indexOf('\r', i);
-                if (end1 < 0)  end1 = len;
-                if (end2 < 0)  end2 = len;
-                i = Math.min(end1, end2);
-            } else if (ch == '\\') {
-                // Map a character reference to its decimal code.
-                buf.append((int) layout.charAt(i++));
-            } else if (ch == '0' && layout.startsWith("0x", i-1)) {
-                // Map a hex numeral to its decimal code.
-                int start = i-1;
-                int end = start+2;
-                while (end < len) {
-                    int dig = layout.charAt(end);
-                    if ((dig >= '0' && dig <= '9') ||
-                        (dig >= 'a' && dig <= 'f'))
-                        ++end;
-                    else
-                        break;
-                }
-                if (end > start) {
-                    String num = layout.substring(start, end);
-                    buf.append(Integer.decode(num));
-                    i = end;
-                } else {
-                    buf.append(ch);
-                }
-            } else {
-                buf.append(ch);
-            }
-        }
-        String result = buf.toString();
-        if (false && !result.equals(layout)) {
-            Utils.log.info("Normalizing layout string");
-            Utils.log.info("    From: "+layout);
-            Utils.log.info("    To:   "+result);
-        }
-        return result;
-    }
-
-    /// Subroutines for parsing and unparsing:
-
-    /** Parse the attribute layout language.
-<pre>
-  attribute_layout:
-        ( layout_element )* | ( callable )+
-  layout_element:
-        ( integral | replication | union | call | reference )
-
-  callable:
-        '[' body ']'
-  body:
-        ( layout_element )+
-
-  integral:
-        ( unsigned_int | signed_int | bc_index | bc_offset | flag )
-  unsigned_int:
-        uint_type
-  signed_int:
-        'S' uint_type
-  any_int:
-        ( unsigned_int | signed_int )
-  bc_index:
-        ( 'P' uint_type | 'PO' uint_type )
-  bc_offset:
-        'O' any_int
-  flag:
-        'F' uint_type
-  uint_type:
-        ( 'B' | 'H' | 'I' | 'V' )
-
-  replication:
-        'N' uint_type '[' body ']'
-
-  union:
-        'T' any_int (union_case)* '(' ')' '[' (body)? ']'
-  union_case:
-        '(' union_case_tag (',' union_case_tag)* ')' '[' (body)? ']'
-  union_case_tag:
-        ( numeral | numeral '-' numeral )
-  call:
-        '(' numeral ')'
-
-  reference:
-        reference_type ( 'N' )? uint_type
-  reference_type:
-        ( constant_ref | schema_ref | utf8_ref | untyped_ref )
-  constant_ref:
-        ( 'KI' | 'KJ' | 'KF' | 'KD' | 'KS' | 'KQ' | 'KM' | 'KT' | 'KL' )
-  schema_ref:
-        ( 'RC' | 'RS' | 'RD' | 'RF' | 'RM' | 'RI' | 'RY' | 'RB' | 'RN' )
-  utf8_ref:
-        'RU'
-  untyped_ref:
-        'RQ'
-
-  numeral:
-        '(' ('-')? (digit)+ ')'
-  digit:
-        ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' )
- </pre>
-    */
-    static //private
-    Layout.Element[] tokenizeLayout(Layout self, int curCble, String layout) {
-        List<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, List<Layout.Element> col) {
-        boolean prevBCI = false;
-        for (int len = layout.length(), i = 0; i < len; ) {
-            int start = i;
-            int body;
-            Layout.Element e = self.new Element();
-            byte kind;
-            //System.out.println("at "+i+": ..."+layout.substring(i));
-            // strip a prefix
-            switch (layout.charAt(i++)) {
-            /// layout_element: integral
-            case 'B': case 'H': case 'I': case 'V': // unsigned_int
-                kind = EK_INT;
-                --i; // reparse
-                i = tokenizeUInt(e, layout, i);
-                break;
-            case 'S': // signed_int
-                kind = EK_INT;
-                --i; // reparse
-                i = tokenizeSInt(e, layout, i);
-                break;
-            case 'P': // bc_index
-                kind = EK_BCI;
-                if (layout.charAt(i++) == 'O') {
-                    // bc_index: 'PO' tokenizeUInt
-                    e.flags |= EF_DELTA;
-                    // must follow P or PO:
-                    if (!prevBCI)
-                        { i = -i; continue; } // fail
-                    i++; // move forward
-                }
-                --i; // reparse
-                i = tokenizeUInt(e, layout, i);
-                break;
-            case 'O': // bc_offset
-                kind = EK_BCO;
-                e.flags |= EF_DELTA;
-                // must follow P or PO:
-                if (!prevBCI)
-                    { i = -i; continue; } // fail
-                i = tokenizeSInt(e, layout, i);
-                break;
-            case 'F': // flag
-                kind = EK_FLAG;
-                i = tokenizeUInt(e, layout, i);
-                break;
-            case 'N': // replication: 'N' uint '[' elem ... ']'
-                kind = EK_REPL;
-                i = tokenizeUInt(e, layout, i);
-                if (layout.charAt(i++) != '[')
-                    { i = -i; continue; } // fail
-                i = skipBody(layout, body = i);
-                e.body = tokenizeLayout(self, curCble,
-                                        layout.substring(body, i++));
-                break;
-            case 'T': // union: 'T' any_int union_case* '(' ')' '[' body ']'
-                kind = EK_UN;
-                i = tokenizeSInt(e, layout, i);
-                List<Layout.Element> cases = new ArrayList<>();
-                for (;;) {
-                    // Keep parsing cases until we hit the default case.
-                    if (layout.charAt(i++) != '(')
-                        { i = -i; break; } // fail
-                    int beg = i;
-                    i = layout.indexOf(')', i);
-                    String cstr = layout.substring(beg, i++);
-                    int cstrlen = cstr.length();
-                    if (layout.charAt(i++) != '[')
-                        { i = -i; break; } // fail
-                    // Check for duplication.
-                    if (layout.charAt(i) == ']')
-                        body = i;  // missing body, which is legal here
-                    else
-                        i = skipBody(layout, body = i);
-                    Layout.Element[] cbody
-                        = tokenizeLayout(self, curCble,
-                                         layout.substring(body, i++));
-                    if (cstrlen == 0) {
-                        Layout.Element ce = self.new Element();
-                        ce.body = cbody;
-                        ce.kind = EK_CASE;
-                        ce.removeBand();
-                        cases.add(ce);
-                        break;  // done with the whole union
-                    } else {
-                        // Parse a case string.
-                        boolean firstCaseNum = true;
-                        for (int cp = 0, endp;; cp = endp+1) {
-                            // Look for multiple case tags:
-                            endp = cstr.indexOf(',', cp);
-                            if (endp < 0)  endp = cstrlen;
-                            String cstr1 = cstr.substring(cp, endp);
-                            if (cstr1.isEmpty())
-                                cstr1 = "empty";  // will fail parse
-                            int value0, value1;
-                            // Check for a case range (new in 1.6).
-                            int dash = findCaseDash(cstr1, 0);
-                            if (dash >= 0) {
-                                value0 = parseIntBefore(cstr1, dash);
-                                value1 = parseIntAfter(cstr1, dash);
-                                if (value0 >= value1)
-                                    { i = -i; break; } // fail
-                            } else {
-                                value0 = value1 = Integer.parseInt(cstr1);
-                            }
-                            // Add a case for each value in value0..value1
-                            for (;; value0++) {
-                                Layout.Element ce = self.new Element();
-                                ce.body = cbody;  // all cases share one body
-                                ce.kind = EK_CASE;
-                                ce.removeBand();
-                                if (!firstCaseNum)
-                                    // "backward case" repeats a body
-                                    ce.flags |= EF_BACK;
-                                firstCaseNum = false;
-                                ce.value = value0;
-                                cases.add(ce);
-                                if (value0 == value1)  break;
-                            }
-                            if (endp == cstrlen) {
-                                break;  // done with this case
-                            }
-                        }
-                    }
-                }
-                e.body = new Layout.Element[cases.size()];
-                cases.toArray(e.body);
-                e.kind = kind;
-                for (int j = 0; j < e.body.length-1; j++) {
-                    Layout.Element ce = e.body[j];
-                    if (matchCase(e, ce.value) != ce) {
-                        // Duplicate tag.
-                        { i = -i; break; } // fail
-                    }
-                }
-                break;
-            case '(': // call: '(' '-'? digit+ ')'
-                kind = EK_CALL;
-                e.removeBand();
-                i = layout.indexOf(')', i);
-                String cstr = layout.substring(start+1, i++);
-                int offset = Integer.parseInt(cstr);
-                int target = curCble + offset;
-                if (!(offset+"").equals(cstr) ||
-                    self.elems == null ||
-                    target < 0 ||
-                    target >= self.elems.length)
-                    { i = -i; continue; } // fail
-                Layout.Element ce = self.elems[target];
-                assert(ce.kind == EK_CBLE);
-                e.value = target;
-                e.body = new Layout.Element[]{ ce };
-                // Is it a (recursive) backward call?
-                if (offset <= 0) {
-                    // Yes.  Mark both caller and callee backward.
-                    e.flags  |= EF_BACK;
-                    ce.flags |= EF_BACK;
-                }
-                break;
-            case 'K':  // reference_type: constant_ref
-                kind = EK_REF;
-                switch (layout.charAt(i++)) {
-                case 'I': e.refKind = CONSTANT_Integer; break;
-                case 'J': e.refKind = CONSTANT_Long; break;
-                case 'F': e.refKind = CONSTANT_Float; break;
-                case 'D': e.refKind = CONSTANT_Double; break;
-                case 'S': e.refKind = CONSTANT_String; break;
-                case 'Q': e.refKind = CONSTANT_FieldSpecific; break;
-
-                // new in 1.7:
-                case 'M': e.refKind = CONSTANT_MethodHandle; break;
-                case 'T': e.refKind = CONSTANT_MethodType; break;
-                case 'L': e.refKind = CONSTANT_LoadableValue; break;
-                default: { i = -i; continue; } // fail
-                }
-                break;
-            case 'R': // schema_ref
-                kind = EK_REF;
-                switch (layout.charAt(i++)) {
-                case 'C': e.refKind = CONSTANT_Class; break;
-                case 'S': e.refKind = CONSTANT_Signature; break;
-                case 'D': e.refKind = CONSTANT_NameandType; break;
-                case 'F': e.refKind = CONSTANT_Fieldref; break;
-                case 'M': e.refKind = CONSTANT_Methodref; break;
-                case 'I': e.refKind = CONSTANT_InterfaceMethodref; break;
-
-                case 'U': e.refKind = CONSTANT_Utf8; break; //utf8_ref
-                case 'Q': e.refKind = CONSTANT_All; break; //untyped_ref
-
-                // new in 1.7:
-                case 'Y': e.refKind = CONSTANT_InvokeDynamic; break;
-                case 'B': e.refKind = CONSTANT_BootstrapMethod; break;
-                case 'N': e.refKind = CONSTANT_AnyMember; break;
-
-                default: { i = -i; continue; } // fail
-                }
-                break;
-            default: { i = -i; continue; } // fail
-            }
-
-            // further parsing of refs
-            if (kind == EK_REF) {
-                // reference: reference_type -><- ( 'N' )? tokenizeUInt
-                if (layout.charAt(i++) == 'N') {
-                    e.flags |= EF_NULL;
-                    i++; // move forward
-                }
-                --i; // reparse
-                i = tokenizeUInt(e, layout, i);
-                self.hasRefs = true;
-            }
-
-            prevBCI = (kind == EK_BCI);
-
-            // store the new element
-            e.kind = kind;
-            e.layout = layout.substring(start, i);
-            col.add(e);
-        }
-    }
-    static //private
-    String[] splitBodies(String layout) {
-        List<String> bodies = new ArrayList<>();
-        // Parse several independent layout bodies:  "[foo][bar]...[baz]"
-        for (int i = 0; i < layout.length(); i++) {
-            if (layout.charAt(i++) != '[')
-                layout.charAt(-i);  // throw error
-            int body;
-            i = skipBody(layout, body = i);
-            bodies.add(layout.substring(body, i));
-        }
-        String[] res = new String[bodies.size()];
-        bodies.toArray(res);
-        return res;
-    }
-    private static
-    int skipBody(String layout, int i) {
-        assert(layout.charAt(i-1) == '[');
-        if (layout.charAt(i) == ']')
-            // No empty bodies, please.
-            return -i;
-        // skip balanced [...[...]...]
-        for (int depth = 1; depth > 0; ) {
-            switch (layout.charAt(i++)) {
-            case '[': depth++; break;
-            case ']': depth--; break;
-            }
-        }
-        --i;  // get before bracket
-        assert(layout.charAt(i) == ']');
-        return i;  // return closing bracket
-    }
-    private static
-    int tokenizeUInt(Layout.Element e, String layout, int i) {
-        switch (layout.charAt(i++)) {
-        case 'V': e.len = 0; break;
-        case 'B': e.len = 1; break;
-        case 'H': e.len = 2; break;
-        case 'I': e.len = 4; break;
-        default: return -i;
-        }
-        return i;
-    }
-    private static
-    int tokenizeSInt(Layout.Element e, String layout, int i) {
-        if (layout.charAt(i) == 'S') {
-            e.flags |= EF_SIGN;
-            ++i;
-        }
-        return tokenizeUInt(e, layout, i);
-    }
-
-    private static
-    boolean isDigit(char c) {
-        return c >= '0' && c <= '9';
-    }
-
-    /** Find an occurrence of hyphen '-' between two numerals. */
-    static //private
-    int findCaseDash(String layout, int fromIndex) {
-        if (fromIndex <= 0)  fromIndex = 1;  // minimum dash pos
-        int lastDash = layout.length() - 2;  // maximum dash pos
-        for (;;) {
-            int dash = layout.indexOf('-', fromIndex);
-            if (dash < 0 || dash > lastDash)  return -1;
-            if (isDigit(layout.charAt(dash-1))) {
-                char afterDash = layout.charAt(dash+1);
-                if (afterDash == '-' && dash+2 < layout.length())
-                    afterDash = layout.charAt(dash+2);
-                if (isDigit(afterDash)) {
-                    // matched /[0-9]--?[0-9]/; return position of dash
-                    return dash;
-                }
-            }
-            fromIndex = dash+1;
-        }
-    }
-    static
-    int parseIntBefore(String layout, int dash) {
-        int end = dash;
-        int beg = end;
-        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;
-        assert(beg == 0 || !isDigit(layout.charAt(beg-1)));
-        return Integer.parseInt(layout.substring(beg, end));
-    }
-    static
-    int parseIntAfter(String layout, int dash) {
-        int beg = dash+1;
-        int end = beg;
-        int limit = layout.length();
-        if (end < limit && 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));
-    }
-    /** For compatibility with 1.5 pack, expand 1-5 into 1,2,3,4,5. */
-    static
-    String expandCaseDashNotation(String layout) {
-        int dash = findCaseDash(layout, 0);
-        if (dash < 0)  return layout;  // no dashes (the common case)
-        StringBuilder result = new StringBuilder(layout.length() * 3);
-        int sofar = 0;  // how far have we processed the layout?
-        for (;;) {
-            // for each dash, collect everything up to the dash
-            result.append(layout, sofar, dash);
-            sofar = dash+1;  // skip the dash
-            // then collect intermediate values
-            int value0 = parseIntBefore(layout, dash);
-            int value1 = parseIntAfter(layout, dash);
-            assert(value0 < value1);
-            result.append(",");  // close off value0 numeral
-            for (int i = value0+1; i < value1; i++) {
-                result.append(i);
-                result.append(",");  // close off i numeral
-            }
-            dash = findCaseDash(layout, sofar);
-            if (dash < 0)  break;
-        }
-        result.append(layout, sofar, layout.length());  // collect the rest
-        return result.toString();
-    }
-    static {
-        assert(expandCaseDashNotation("1-5").equals("1,2,3,4,5"));
-        assert(expandCaseDashNotation("-2--1").equals("-2,-1"));
-        assert(expandCaseDashNotation("-2-1").equals("-2,-1,0,1"));
-        assert(expandCaseDashNotation("-1-0").equals("-1,0"));
-    }
-
-    // Parse attribute bytes, putting values into bands.  Returns new pos.
-    // Used when reading a class file (local refs resolved with local cpMap).
-    // Also used for ad hoc scanning.
-    static
-    int parseUsing(Layout.Element[] elems, Holder holder,
-                   byte[] bytes, int pos, int len, ValueStream out) {
-        int prevBCI = 0;
-        int prevRBCI = 0;
-        int end = pos + len;
-        int[] buf = { 0 };  // for calls to parseInt, holds 2nd result
-        for (int i = 0; i < elems.length; i++) {
-            Layout.Element e = elems[i];
-            int bandIndex = e.bandIndex;
-            int value;
-            int BCI, RBCI;
-            switch (e.kind) {
-            case EK_INT:
-                pos = parseInt(e, bytes, pos, buf);
-                value = buf[0];
-                out.putInt(bandIndex, value);
-                break;
-            case EK_BCI:  // PH, POH
-                pos = parseInt(e, bytes, pos, buf);
-                BCI = buf[0];
-                RBCI = out.encodeBCI(BCI);
-                if (!e.flagTest(EF_DELTA)) {
-                    // PH:  transmit R(bci), store bci
-                    value = RBCI;
-                } else {
-                    // POH:  transmit D(R(bci)), store bci
-                    value = RBCI - prevRBCI;
-                }
-                prevBCI = BCI;
-                prevRBCI = RBCI;
-                out.putInt(bandIndex, value);
-                break;
-            case EK_BCO:  // OH
-                assert(e.flagTest(EF_DELTA));
-                // OH:  transmit D(R(bci)), store D(bci)
-                pos = parseInt(e, bytes, pos, buf);
-                BCI = prevBCI + buf[0];
-                RBCI = out.encodeBCI(BCI);
-                value = RBCI - prevRBCI;
-                prevBCI = BCI;
-                prevRBCI = RBCI;
-                out.putInt(bandIndex, value);
-                break;
-            case EK_FLAG:
-                pos = parseInt(e, bytes, pos, buf);
-                value = buf[0];
-                out.putInt(bandIndex, value);
-                break;
-            case EK_REPL:
-                pos = parseInt(e, bytes, pos, buf);
-                value = buf[0];
-                out.putInt(bandIndex, value);
-                for (int j = 0; j < value; j++) {
-                    pos = parseUsing(e.body, holder, bytes, pos, end-pos, out);
-                }
-                break;  // already transmitted the scalar value
-            case EK_UN:
-                pos = parseInt(e, bytes, pos, buf);
-                value = buf[0];
-                out.putInt(bandIndex, value);
-                Layout.Element ce = matchCase(e, value);
-                pos = parseUsing(ce.body, holder, bytes, pos, end-pos, out);
-
-                break;  // already transmitted the scalar value
-            case EK_CALL:
-                // Adjust band offset if it is a backward call.
-                assert(e.body.length == 1);
-                assert(e.body[0].kind == EK_CBLE);
-                if (e.flagTest(EF_BACK))
-                    out.noteBackCall(e.value);
-                pos = parseUsing(e.body[0].body, holder, bytes, pos, end-pos, out);
-                break;  // no additional scalar value to transmit
-            case EK_REF:
-                pos = parseInt(e, bytes, pos, buf);
-                int localRef = buf[0];
-                Entry globalRef;
-                if (localRef == 0) {
-                    globalRef = null;  // N.B. global null reference is -1
-                } else {
-                    Entry[] cpMap = holder.getCPMap();
-                    globalRef = (localRef >= 0 && localRef < cpMap.length
-                                    ? cpMap[localRef]
-                                    : null);
-                    byte tag = e.refKind;
-                    if (globalRef != null && tag == CONSTANT_Signature
-                        && globalRef.getTag() == CONSTANT_Utf8) {
-                        // Cf. ClassReader.readSignatureRef.
-                        String typeName = globalRef.stringValue();
-                        globalRef = ConstantPool.getSignatureEntry(typeName);
-                    }
-                    String got = (globalRef == null
-                        ? "invalid CP index"
-                        : "type=" + ConstantPool.tagName(globalRef.tag));
-                    if (globalRef == null || !globalRef.tagMatches(tag)) {
-                        throw new IllegalArgumentException(
-                                "Bad constant, expected type=" +
-                                ConstantPool.tagName(tag) + " got " + got);
-                    }
-                }
-                out.putRef(bandIndex, globalRef);
-                break;
-            default: assert(false);
-            }
-        }
-        return pos;
-    }
-
-    static
-    Layout.Element matchCase(Layout.Element e, int value) {
-        assert(e.kind == EK_UN);
-        int lastj = e.body.length-1;
-        for (int j = 0; j < lastj; j++) {
-            Layout.Element ce = e.body[j];
-            assert(ce.kind == EK_CASE);
-            if (value == ce.value)
-                return ce;
-        }
-        return e.body[lastj];
-    }
-
-    private static
-    int parseInt(Layout.Element e, byte[] bytes, int pos, int[] buf) {
-        int value = 0;
-        int loBits = e.len * 8;
-        // Read in big-endian order:
-        for (int bitPos = loBits; (bitPos -= 8) >= 0; ) {
-            value += (bytes[pos++] & 0xFF) << bitPos;
-        }
-        if (loBits < 32 && e.flagTest(EF_SIGN)) {
-            // sign-extend subword value
-            int hiBits = 32 - loBits;
-            value = (value << hiBits) >> hiBits;
-        }
-        buf[0] = value;
-        return pos;
-    }
-
-    // Format attribute bytes, drawing values from bands.
-    // Used when emptying attribute bands into a package model.
-    // (At that point CP refs. are not yet assigned indexes.)
-    static
-    void unparseUsing(Layout.Element[] elems, Object[] fixups,
-                      ValueStream in, ByteArrayOutputStream out) {
-        int prevBCI = 0;
-        int prevRBCI = 0;
-        for (int i = 0; i < elems.length; i++) {
-            Layout.Element e = elems[i];
-            int bandIndex = e.bandIndex;
-            int value;
-            int BCI, RBCI;  // "RBCI" is R(BCI), BCI's coded representation
-            switch (e.kind) {
-            case EK_INT:
-                value = in.getInt(bandIndex);
-                unparseInt(e, value, out);
-                break;
-            case EK_BCI:  // PH, POH
-                value = in.getInt(bandIndex);
-                if (!e.flagTest(EF_DELTA)) {
-                    // PH:  transmit R(bci), store bci
-                    RBCI = value;
-                } else {
-                    // POH:  transmit D(R(bci)), store bci
-                    RBCI = prevRBCI + value;
-                }
-                assert(prevBCI == in.decodeBCI(prevRBCI));
-                BCI = in.decodeBCI(RBCI);
-                unparseInt(e, BCI, out);
-                prevBCI = BCI;
-                prevRBCI = RBCI;
-                break;
-            case EK_BCO:  // OH
-                value = in.getInt(bandIndex);
-                assert(e.flagTest(EF_DELTA));
-                // OH:  transmit D(R(bci)), store D(bci)
-                assert(prevBCI == in.decodeBCI(prevRBCI));
-                RBCI = prevRBCI + value;
-                BCI = in.decodeBCI(RBCI);
-                unparseInt(e, BCI - prevBCI, out);
-                prevBCI = BCI;
-                prevRBCI = RBCI;
-                break;
-            case EK_FLAG:
-                value = in.getInt(bandIndex);
-                unparseInt(e, value, out);
-                break;
-            case EK_REPL:
-                value = in.getInt(bandIndex);
-                unparseInt(e, value, out);
-                for (int j = 0; j < value; j++) {
-                    unparseUsing(e.body, fixups, in, out);
-                }
-                break;
-            case EK_UN:
-                value = in.getInt(bandIndex);
-                unparseInt(e, value, out);
-                Layout.Element ce = matchCase(e, value);
-                unparseUsing(ce.body, fixups, in, out);
-                break;
-            case EK_CALL:
-                assert(e.body.length == 1);
-                assert(e.body[0].kind == EK_CBLE);
-                unparseUsing(e.body[0].body, fixups, in, out);
-                break;
-            case EK_REF:
-                Entry globalRef = in.getRef(bandIndex);
-                int localRef;
-                if (globalRef != null) {
-                    // It's a one-element array, really an lvalue.
-                    fixups[0] = Fixups.addRefWithLoc(fixups[0], out.size(), globalRef);
-                    localRef = 0; // placeholder for fixups
-                } else {
-                    localRef = 0; // fixed null value
-                }
-                unparseInt(e, localRef, out);
-                break;
-            default: assert(false); continue;
-            }
-        }
-    }
-
-    private static
-    void unparseInt(Layout.Element e, int value, ByteArrayOutputStream out) {
-        int loBits = e.len * 8;
-        if (loBits == 0) {
-            // It is not stored at all ('V' layout).
-            return;
-        }
-        if (loBits < 32) {
-            int hiBits = 32 - loBits;
-            int codedValue;
-            if (e.flagTest(EF_SIGN))
-                codedValue = (value << hiBits) >> hiBits;
-            else
-                codedValue = (value << hiBits) >>> hiBits;
-            if (codedValue != value)
-                throw new InternalError("cannot code in "+e.len+" bytes: "+value);
-        }
-        // Write in big-endian order:
-        for (int bitPos = loBits; (bitPos -= 8) >= 0; ) {
-            out.write((byte)(value >>> bitPos));
-        }
-    }
-
-/*
-    /// Testing.
-    public static void main(String av[]) {
-        int maxVal = 12;
-        int iters = 0;
-        boolean verbose;
-        int ap = 0;
-        while (ap < av.length) {
-            if (!av[ap].startsWith("-"))  break;
-            if (av[ap].startsWith("-m"))
-                maxVal = Integer.parseInt(av[ap].substring(2));
-            else if (av[ap].startsWith("-i"))
-                iters = Integer.parseInt(av[ap].substring(2));
-            else
-                throw new RuntimeException("Bad option: "+av[ap]);
-            ap++;
-        }
-        verbose = (iters == 0);
-        if (iters <= 0)  iters = 1;
-        if (ap == av.length) {
-            av = new String[] {
-                "HH",         // ClassFile.version
-                "RUH",        // SourceFile
-                "RCHRDNH",    // EnclosingMethod
-                "KQH",        // ConstantValue
-                "NH[RCH]",    // Exceptions
-                "NH[PHH]",    // LineNumberTable
-                "NH[PHOHRUHRSHH]",      // LocalVariableTable
-                "NH[PHPOHIIH]",         // CharacterRangeTable
-                "NH[PHHII]",            // CoverageTable
-                "NH[RCHRCNHRUNHFH]",    // InnerClasses
-                "NH[RMHNH[KLH]]",       // BootstrapMethods
-                "HHNI[B]NH[PHPOHPOHRCNH]NH[RUHNI[B]]", // Code
-                "=AnnotationDefault",
-                // Like metadata, but with a compact tag set:
-                "[NH[(1)]]"
-                +"[NH[(1)]]"
-                +"[RSHNH[RUH(1)]]"
-                +"[TB(0,1,3)[KIH](2)[KDH](5)[KFH](4)[KJH](7)[RSH](8)[RSHRUH](9)[RUH](10)[(-1)](6)[NH[(0)]]()[]]",
-                ""
-            };
-            ap = 0;
-        }
-        Utils.currentInstance.set(new PackerImpl());
-        final int[][] counts = new int[2][3];  // int bci ref
-        final Entry[] cpMap = new Entry[maxVal+1];
-        for (int i = 0; i < cpMap.length; i++) {
-            if (i == 0)  continue;  // 0 => null
-            cpMap[i] = ConstantPool.getLiteralEntry(new Integer(i));
-        }
-        Package.Class cls = new Package().new Class("");
-        cls.cpMap = cpMap;
-        class TestValueStream extends ValueStream {
-            java.util.Random rand = new java.util.Random(0);
-            ArrayList history = new ArrayList();
-            int ckidx = 0;
-            int maxVal;
-            boolean verbose;
-            void reset() { history.clear(); ckidx = 0; }
-            public int getInt(int bandIndex) {
-                counts[0][0]++;
-                int value = rand.nextInt(maxVal+1);
-                history.add(new Integer(bandIndex));
-                history.add(new Integer(value));
-                return value;
-            }
-            public void putInt(int bandIndex, int token) {
-                counts[1][0]++;
-                if (verbose)
-                    System.out.print(" "+bandIndex+":"+token);
-                // Make sure this put parallels a previous get:
-                int check0 = ((Integer)history.get(ckidx+0)).intValue();
-                int check1 = ((Integer)history.get(ckidx+1)).intValue();
-                if (check0 != bandIndex || check1 != token) {
-                    if (!verbose)
-                        System.out.println(history.subList(0, ckidx));
-                    System.out.println(" *** Should be "+check0+":"+check1);
-                    throw new RuntimeException("Failed test!");
-                }
-                ckidx += 2;
-            }
-            public Entry getRef(int bandIndex) {
-                counts[0][2]++;
-                int value = getInt(bandIndex);
-                if (value < 0 || value > maxVal) {
-                    System.out.println(" *** Unexpected ref code "+value);
-                    return ConstantPool.getLiteralEntry(new Integer(value));
-                }
-                return cpMap[value];
-            }
-            public void putRef(int bandIndex, Entry ref) {
-                counts[1][2]++;
-                if (ref == null) {
-                    putInt(bandIndex, 0);
-                    return;
-                }
-                Number refValue = null;
-                if (ref instanceof ConstantPool.NumberEntry)
-                    refValue = ((ConstantPool.NumberEntry)ref).numberValue();
-                int value;
-                if (!(refValue instanceof Integer)) {
-                    System.out.println(" *** Unexpected ref "+ref);
-                    value = -1;
-                } else {
-                    value = ((Integer)refValue).intValue();
-                }
-                putInt(bandIndex, value);
-            }
-            public int encodeBCI(int bci) {
-                counts[1][1]++;
-                // move LSB to MSB of low byte
-                int code = (bci >> 8) << 8;  // keep high bits
-                code += (bci & 0xFE) >> 1;
-                code += (bci & 0x01) << 7;
-                return code ^ (8<<8);  // mark it clearly as coded
-            }
-            public int decodeBCI(int bciCode) {
-                counts[0][1]++;
-                bciCode ^= (8<<8);  // remove extra mark
-                int bci = (bciCode >> 8) << 8;  // keep high bits
-                bci += (bciCode & 0x7F) << 1;
-                bci += (bciCode & 0x80) >> 7;
-                return bci;
-            }
-        }
-        TestValueStream tts = new TestValueStream();
-        tts.maxVal = maxVal;
-        tts.verbose = verbose;
-        ByteArrayOutputStream buf = new ByteArrayOutputStream();
-        for (int i = 0; i < (1 << 30); i = (i + 1) * 5) {
-            int ei = tts.encodeBCI(i);
-            int di = tts.decodeBCI(ei);
-            if (di != i)  System.out.println("i="+Integer.toHexString(i)+
-                                             " ei="+Integer.toHexString(ei)+
-                                             " di="+Integer.toHexString(di));
-        }
-        while (iters-- > 0) {
-            for (int i = ap; i < av.length; i++) {
-                String layout = av[i];
-                if (layout.startsWith("=")) {
-                    String name = layout.substring(1);
-                    for (Attribute a : standardDefs.values()) {
-                        if (a.name().equals(name)) {
-                            layout = a.layout().layout();
-                            break;
-                        }
-                    }
-                    if (layout.startsWith("=")) {
-                        System.out.println("Could not find "+name+" in "+standardDefs.values());
-                    }
-                }
-                Layout self = new Layout(0, "Foo", layout);
-                if (verbose) {
-                    System.out.print("/"+layout+"/ => ");
-                    System.out.println(Arrays.asList(self.elems));
-                }
-                buf.reset();
-                tts.reset();
-                Object fixups = self.unparse(tts, buf);
-                byte[] bytes = buf.toByteArray();
-                // Attach the references to the byte array.
-                Fixups.setBytes(fixups, bytes);
-                // Patch the references to their frozen values.
-                Fixups.finishRefs(fixups, bytes, new Index("test", cpMap));
-                if (verbose) {
-                    System.out.print("  bytes: {");
-                    for (int j = 0; j < bytes.length; j++) {
-                        System.out.print(" "+bytes[j]);
-                    }
-                    System.out.println("}");
-                }
-                if (verbose) {
-                    System.out.print("  parse: {");
-                }
-                self.parse(cls, bytes, 0, bytes.length, tts);
-                if (verbose) {
-                    System.out.println("}");
-                }
-            }
-        }
-        for (int j = 0; j <= 1; j++) {
-            System.out.print("values "+(j==0?"read":"written")+": {");
-            for (int k = 0; k < counts[j].length; k++) {
-                System.out.print(" "+counts[j][k]);
-            }
-            System.out.println(" }");
-        }
-    }
-//*/
-}
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/BandStructure.java	Mon Dec 09 15:28:46 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2762 +0,0 @@
-/*
- * Copyright (c) 2001, 2013, 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.Entry;
-import com.sun.java.util.jar.pack.ConstantPool.Index;
-import com.sun.java.util.jar.pack.Package.Class.Field;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.EOFException;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FilterInputStream;
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.jar.Pack200;
-import static com.sun.java.util.jar.pack.Constants.*;
-import java.util.LinkedList;
-
-/**
- * Define the structure and ordering of "bands" in a packed file.
- * @author John Rose
- */
-@SuppressWarnings({"removal"})
-abstract
-class BandStructure {
-    static final int MAX_EFFORT = 9;
-    static final int MIN_EFFORT = 1;
-    static final int DEFAULT_EFFORT = 5;
-
-    // Inherit options from Pack200:
-    PropMap p200 = Utils.currentPropMap();
-
-    int verbose = p200.getInteger(Utils.DEBUG_VERBOSE);
-    int effort = p200.getInteger(Pack200.Packer.EFFORT);
-    { if (effort == 0)  effort = DEFAULT_EFFORT; }
-    boolean optDumpBands = p200.getBoolean(Utils.COM_PREFIX+"dump.bands");
-    boolean optDebugBands = p200.getBoolean(Utils.COM_PREFIX+"debug.bands");
-
-    // Various heuristic options.
-    boolean optVaryCodings = !p200.getBoolean(Utils.COM_PREFIX+"no.vary.codings");
-    boolean optBigStrings = !p200.getBoolean(Utils.COM_PREFIX+"no.big.strings");
-
-    protected abstract Index getCPIndex(byte tag);
-
-    // Local copy of highest class version.
-    private Package.Version highestClassVersion = null;
-
-    /** Call this exactly once, early, to specify the archive major version. */
-    public void initHighestClassVersion(Package.Version highestClassVersion) throws IOException {
-        if (this.highestClassVersion != null) {
-            throw new IOException(
-                "Highest class major version is already initialized to " +
-                this.highestClassVersion + "; new setting is " + highestClassVersion);
-        }
-        this.highestClassVersion = highestClassVersion;
-        adjustToClassVersion();
-    }
-
-    public Package.Version getHighestClassVersion() {
-        return highestClassVersion;
-    }
-
-    private final boolean isReader = this instanceof PackageReader;
-
-    protected BandStructure() {}
-
-    static final Coding BYTE1 = Coding.of(1,256);
-
-    static final Coding CHAR3 = Coding.of(3,128);
-    // Note:  Tried sharper (3,16) with no post-zip benefit.
-
-    // This is best used with BCI values:
-    static final Coding BCI5 = Coding.of(5,4);  // mostly 1-byte offsets
-    static final Coding BRANCH5 = Coding.of(5,4,2); // mostly forward branches
-
-    static final Coding UNSIGNED5 = Coding.of(5,64);
-    static final Coding UDELTA5 = UNSIGNED5.getDeltaCoding();
-    // "sharp" (5,64) zips 0.4% better than "medium" (5,128)
-    // It zips 1.1% better than "flat" (5,192)
-
-    static final Coding SIGNED5 = Coding.of(5,64,1);  //sharp
-    static final Coding DELTA5 = SIGNED5.getDeltaCoding();
-    // Note:  Tried (5,128,2) and (5,192,2) with no benefit.
-
-    static final Coding MDELTA5 = Coding.of(5,64,2).getDeltaCoding();
-
-    private static final Coding[] basicCodings = {
-        // Table of "Canonical BHSD Codings" from Pack200 spec.
-        null,  // _meta_default
-
-        // Fixed-length codings:
-        Coding.of(1,256,0),
-        Coding.of(1,256,1),
-        Coding.of(1,256,0).getDeltaCoding(),
-        Coding.of(1,256,1).getDeltaCoding(),
-        Coding.of(2,256,0),
-        Coding.of(2,256,1),
-        Coding.of(2,256,0).getDeltaCoding(),
-        Coding.of(2,256,1).getDeltaCoding(),
-        Coding.of(3,256,0),
-        Coding.of(3,256,1),
-        Coding.of(3,256,0).getDeltaCoding(),
-        Coding.of(3,256,1).getDeltaCoding(),
-        Coding.of(4,256,0),
-        Coding.of(4,256,1),
-        Coding.of(4,256,0).getDeltaCoding(),
-        Coding.of(4,256,1).getDeltaCoding(),
-
-        // Full-range variable-length codings:
-        Coding.of(5,  4,0),
-        Coding.of(5,  4,1),
-        Coding.of(5,  4,2),
-        Coding.of(5, 16,0),
-        Coding.of(5, 16,1),
-        Coding.of(5, 16,2),
-        Coding.of(5, 32,0),
-        Coding.of(5, 32,1),
-        Coding.of(5, 32,2),
-        Coding.of(5, 64,0),
-        Coding.of(5, 64,1),
-        Coding.of(5, 64,2),
-        Coding.of(5,128,0),
-        Coding.of(5,128,1),
-        Coding.of(5,128,2),
-
-        Coding.of(5,  4,0).getDeltaCoding(),
-        Coding.of(5,  4,1).getDeltaCoding(),
-        Coding.of(5,  4,2).getDeltaCoding(),
-        Coding.of(5, 16,0).getDeltaCoding(),
-        Coding.of(5, 16,1).getDeltaCoding(),
-        Coding.of(5, 16,2).getDeltaCoding(),
-        Coding.of(5, 32,0).getDeltaCoding(),
-        Coding.of(5, 32,1).getDeltaCoding(),
-        Coding.of(5, 32,2).getDeltaCoding(),
-        Coding.of(5, 64,0).getDeltaCoding(),
-        Coding.of(5, 64,1).getDeltaCoding(),
-        Coding.of(5, 64,2).getDeltaCoding(),
-        Coding.of(5,128,0).getDeltaCoding(),
-        Coding.of(5,128,1).getDeltaCoding(),
-        Coding.of(5,128,2).getDeltaCoding(),
-
-        // Variable length subrange codings:
-        Coding.of(2,192,0),
-        Coding.of(2,224,0),
-        Coding.of(2,240,0),
-        Coding.of(2,248,0),
-        Coding.of(2,252,0),
-
-        Coding.of(2,  8,0).getDeltaCoding(),
-        Coding.of(2,  8,1).getDeltaCoding(),
-        Coding.of(2, 16,0).getDeltaCoding(),
-        Coding.of(2, 16,1).getDeltaCoding(),
-        Coding.of(2, 32,0).getDeltaCoding(),
-        Coding.of(2, 32,1).getDeltaCoding(),
-        Coding.of(2, 64,0).getDeltaCoding(),
-        Coding.of(2, 64,1).getDeltaCoding(),
-        Coding.of(2,128,0).getDeltaCoding(),
-        Coding.of(2,128,1).getDeltaCoding(),
-        Coding.of(2,192,0).getDeltaCoding(),
-        Coding.of(2,192,1).getDeltaCoding(),
-        Coding.of(2,224,0).getDeltaCoding(),
-        Coding.of(2,224,1).getDeltaCoding(),
-        Coding.of(2,240,0).getDeltaCoding(),
-        Coding.of(2,240,1).getDeltaCoding(),
-        Coding.of(2,248,0).getDeltaCoding(),
-        Coding.of(2,248,1).getDeltaCoding(),
-
-        Coding.of(3,192,0),
-        Coding.of(3,224,0),
-        Coding.of(3,240,0),
-        Coding.of(3,248,0),
-        Coding.of(3,252,0),
-
-        Coding.of(3,  8,0).getDeltaCoding(),
-        Coding.of(3,  8,1).getDeltaCoding(),
-        Coding.of(3, 16,0).getDeltaCoding(),
-        Coding.of(3, 16,1).getDeltaCoding(),
-        Coding.of(3, 32,0).getDeltaCoding(),
-        Coding.of(3, 32,1).getDeltaCoding(),
-        Coding.of(3, 64,0).getDeltaCoding(),
-        Coding.of(3, 64,1).getDeltaCoding(),
-        Coding.of(3,128,0).getDeltaCoding(),
-        Coding.of(3,128,1).getDeltaCoding(),
-        Coding.of(3,192,0).getDeltaCoding(),
-        Coding.of(3,192,1).getDeltaCoding(),
-        Coding.of(3,224,0).getDeltaCoding(),
-        Coding.of(3,224,1).getDeltaCoding(),
-        Coding.of(3,240,0).getDeltaCoding(),
-        Coding.of(3,240,1).getDeltaCoding(),
-        Coding.of(3,248,0).getDeltaCoding(),
-        Coding.of(3,248,1).getDeltaCoding(),
-
-        Coding.of(4,192,0),
-        Coding.of(4,224,0),
-        Coding.of(4,240,0),
-        Coding.of(4,248,0),
-        Coding.of(4,252,0),
-
-        Coding.of(4,  8,0).getDeltaCoding(),
-        Coding.of(4,  8,1).getDeltaCoding(),
-        Coding.of(4, 16,0).getDeltaCoding(),
-        Coding.of(4, 16,1).getDeltaCoding(),
-        Coding.of(4, 32,0).getDeltaCoding(),
-        Coding.of(4, 32,1).getDeltaCoding(),
-        Coding.of(4, 64,0).getDeltaCoding(),
-        Coding.of(4, 64,1).getDeltaCoding(),
-        Coding.of(4,128,0).getDeltaCoding(),
-        Coding.of(4,128,1).getDeltaCoding(),
-        Coding.of(4,192,0).getDeltaCoding(),
-        Coding.of(4,192,1).getDeltaCoding(),
-        Coding.of(4,224,0).getDeltaCoding(),
-        Coding.of(4,224,1).getDeltaCoding(),
-        Coding.of(4,240,0).getDeltaCoding(),
-        Coding.of(4,240,1).getDeltaCoding(),
-        Coding.of(4,248,0).getDeltaCoding(),
-        Coding.of(4,248,1).getDeltaCoding(),
-
-        null
-    };
-    private static final Map<Coding, Integer> basicCodingIndexes;
-    static {
-        assert(basicCodings[_meta_default] == null);
-        assert(basicCodings[_meta_canon_min] != null);
-        assert(basicCodings[_meta_canon_max] != null);
-        Map<Coding, Integer> map = new HashMap<>();
-        for (int i = 0; i < basicCodings.length; i++) {
-            Coding c = basicCodings[i];
-            if (c == null)  continue;
-            assert(i >= _meta_canon_min);
-            assert(i <= _meta_canon_max);
-            map.put(c, i);
-        }
-        basicCodingIndexes = map;
-    }
-    public static Coding codingForIndex(int i) {
-        return i < basicCodings.length ? basicCodings[i] : null;
-    }
-    public static int indexOf(Coding c) {
-        Integer i = basicCodingIndexes.get(c);
-        if (i == null)  return 0;
-        return i.intValue();
-    }
-    public static Coding[] getBasicCodings() {
-        return basicCodings.clone();
-    }
-
-    protected byte[] bandHeaderBytes;    // used for input only
-    protected int    bandHeaderBytePos;  // BHB read pointer, for input only
-    protected int    bandHeaderBytePos0; // for debug
-
-    protected CodingMethod getBandHeader(int XB, Coding regularCoding) {
-        CodingMethod[] res = {null};
-        // push back XB onto the band header bytes
-        bandHeaderBytes[--bandHeaderBytePos] = (byte) XB;
-        bandHeaderBytePos0 = bandHeaderBytePos;
-        // scan forward through XB and any additional band header bytes
-        bandHeaderBytePos = parseMetaCoding(bandHeaderBytes,
-                                            bandHeaderBytePos,
-                                            regularCoding,
-                                            res);
-        return res[0];
-    }
-
-    public static int parseMetaCoding(byte[] bytes, int pos, Coding dflt, CodingMethod[] res) {
-        if ((bytes[pos] & 0xFF) == _meta_default) {
-            res[0] = dflt;
-            return pos+1;
-        }
-        int pos2;
-        pos2 = Coding.parseMetaCoding(bytes, pos, dflt, res);
-        if (pos2 > pos)  return pos2;
-        pos2 = PopulationCoding.parseMetaCoding(bytes, pos, dflt, res);
-        if (pos2 > pos)  return pos2;
-        pos2 = AdaptiveCoding.parseMetaCoding(bytes, pos, dflt, res);
-        if (pos2 > pos)  return pos2;
-        throw new RuntimeException("Bad meta-coding op "+(bytes[pos]&0xFF));
-    }
-
-    static final int SHORT_BAND_HEURISTIC = 100;
-
-    public static final int NO_PHASE        = 0;
-
-    // package writing phases:
-    public static final int COLLECT_PHASE   = 1; // collect data before write
-    public static final int FROZEN_PHASE    = 3; // no longer collecting
-    public static final int WRITE_PHASE     = 5; // ready to write bytes
-
-    // package reading phases:
-    public static final int EXPECT_PHASE    = 2; // gather expected counts
-    public static final int READ_PHASE      = 4; // ready to read bytes
-    public static final int DISBURSE_PHASE  = 6; // pass out data after read
-
-    public static final int DONE_PHASE      = 8; // done writing or reading
-
-    static boolean phaseIsRead(int p) {
-        return (p % 2) == 0;
-    }
-    static int phaseCmp(int p0, int p1) {
-        assert((p0 % 2) == (p1 % 2) || (p0 % 8) == 0 || (p1 % 8) == 0);
-        return p0 - p1;
-    }
-
-    /** The packed file is divided up into a number of segments.
-     *  Most segments are typed as ValueBand, strongly-typed sequences
-     *  of integer values, all interpreted in a single way.
-     *  A few segments are ByteBands, which hetergeneous sequences
-     *  of bytes.
-     *
-     *  The two phases for writing a packed file are COLLECT and WRITE.
-     *  1. When writing a packed file, each band collects
-     *  data in an ad-hoc order.
-     *  2. At the end, each band is assigned a coding scheme,
-     *  and then all the bands are written in their global order.
-     *
-     *  The three phases for reading a packed file are EXPECT, READ,
-     *  and DISBURSE.
-     *  1. For each band, the expected number of integers  is determined.
-     *  2. The data is actually read from the file into the band.
-     *  3. The band pays out its values as requested, in an ad hoc order.
-     *
-     *  When the last phase of a band is done, it is marked so (DONE).
-     *  Clearly, these phases must be properly ordered WRT each other.
-     */
-    abstract class Band {
-        private int    phase = NO_PHASE;
-        private final  String name;
-
-        private int    valuesExpected;
-
-        protected long outputSize = -1;  // cache
-
-        public final Coding regularCoding;
-
-        public final int seqForDebug;
-        public int       elementCountForDebug;
-
-
-        protected Band(String name, Coding regularCoding) {
-            this.name = name;
-            this.regularCoding = regularCoding;
-            this.seqForDebug = ++nextSeqForDebug;
-            if (verbose > 2)
-                Utils.log.fine("Band "+seqForDebug+" is "+name);
-            // caller must call init
-        }
-
-        public Band init() {
-            // Cannot due this from the constructor, because constructor
-            // may wish to initialize some subclass variables.
-            // Set initial phase for reading or writing:
-            if (isReader)
-                readyToExpect();
-            else
-                readyToCollect();
-            return this;
-        }
-
-        // common operations
-        boolean isReader() { return isReader; }
-        int phase() { return phase; }
-        String name() { return name; }
-
-        /** Return -1 if data buffer not allocated, else max length. */
-        public abstract int capacity();
-
-        /** Allocate data buffer to specified length. */
-        protected abstract void setCapacity(int cap);
-
-        /** Return current number of values in buffer, which must exist. */
-        public abstract int length();
-
-        protected abstract int valuesRemainingForDebug();
-
-        public final int valuesExpected() {
-            return valuesExpected;
-        }
-
-        /** Write out bytes, encoding the values. */
-        public final void writeTo(OutputStream out) throws IOException {
-            assert(assertReadyToWriteTo(this, out));
-            setPhase(WRITE_PHASE);
-            // subclasses continue by writing their contents to output
-            writeDataTo(out);
-            doneWriting();
-        }
-
-        abstract void chooseBandCodings() throws IOException;
-
-        public final long outputSize() {
-            if (outputSize >= 0) {
-                long size = outputSize;
-                assert(size == computeOutputSize());
-                return size;
-            }
-            return computeOutputSize();
-        }
-
-        protected abstract long computeOutputSize();
-
-        protected abstract void writeDataTo(OutputStream out) throws IOException;
-
-        /** Expect a certain number of values. */
-        void expectLength(int l) {
-            assert(assertPhase(this, EXPECT_PHASE));
-            assert(valuesExpected == 0);  // all at once
-            assert(l >= 0);
-            valuesExpected = l;
-        }
-        /** Expect more values.  (Multiple calls accumulate.) */
-        void expectMoreLength(int l) {
-            assert(assertPhase(this, EXPECT_PHASE));
-            valuesExpected += l;
-        }
-
-
-        /// Phase change markers.
-
-        private void readyToCollect() { // called implicitly by constructor
-            setCapacity(1);
-            setPhase(COLLECT_PHASE);
-        }
-        protected void doneWriting() {
-            assert(assertPhase(this, WRITE_PHASE));
-            setPhase(DONE_PHASE);
-        }
-        private void readyToExpect() { // called implicitly by constructor
-            setPhase(EXPECT_PHASE);
-        }
-        /** Read in bytes, decoding the values. */
-        public final void readFrom(InputStream in) throws IOException {
-            assert(assertReadyToReadFrom(this, in));
-            setCapacity(valuesExpected());
-            setPhase(READ_PHASE);
-            // subclasses continue by reading their contents from input:
-            readDataFrom(in);
-            readyToDisburse();
-        }
-        protected abstract void readDataFrom(InputStream in) throws IOException;
-        protected void readyToDisburse() {
-            if (verbose > 1)  Utils.log.fine("readyToDisburse "+this);
-            setPhase(DISBURSE_PHASE);
-        }
-        public void doneDisbursing() {
-            assert(assertPhase(this, DISBURSE_PHASE));
-            setPhase(DONE_PHASE);
-        }
-        public final void doneWithUnusedBand() {
-            if (isReader) {
-                assert(assertPhase(this, EXPECT_PHASE));
-                assert(valuesExpected() == 0);
-                // Fast forward:
-                setPhase(READ_PHASE);
-                setPhase(DISBURSE_PHASE);
-                setPhase(DONE_PHASE);
-            } else {
-                setPhase(FROZEN_PHASE);
-            }
-        }
-
-        protected void setPhase(int newPhase) {
-            assert(assertPhaseChangeOK(this, phase, newPhase));
-            this.phase = newPhase;
-        }
-
-        protected int lengthForDebug = -1;  // DEBUG ONLY
-        @Override
-        public String toString() {  // DEBUG ONLY
-            int length = (lengthForDebug != -1 ? lengthForDebug : length());
-            String str = name;
-            if (length != 0)
-                str += "[" + length + "]";
-            if (elementCountForDebug != 0)
-                str += "(" + elementCountForDebug + ")";
-            return str;
-        }
-    }
-
-    class ValueBand extends Band {
-        private int[]  values;   // must be null in EXPECT phase
-        private int    length;
-        private int    valuesDisbursed;
-
-        private CodingMethod bandCoding;
-        private byte[] metaCoding;
-
-        protected ValueBand(String name, Coding regularCoding) {
-            super(name, regularCoding);
-        }
-
-        @Override
-        public int capacity() {
-            return values == null ? -1 : values.length;
-        }
-
-        /** Declare predicted or needed capacity. */
-        @Override
-        protected void setCapacity(int cap) {
-            assert(length <= cap);
-            if (cap == -1) { values = null; return; }
-            values = realloc(values, cap);
-        }
-
-        @Override
-        public int length() {
-            return length;
-        }
-        @Override
-        protected int valuesRemainingForDebug() {
-            return length - valuesDisbursed;
-        }
-        protected int valueAtForDebug(int i) {
-            return values[i];
-        }
-
-        void patchValue(int i, int value) {
-            // Only one use for this.
-            assert(this == archive_header_S);
-            assert(i == AH_ARCHIVE_SIZE_HI || i == AH_ARCHIVE_SIZE_LO);
-            assert(i < length);  // must have already output a dummy
-            values[i] = value;
-            outputSize = -1;  // decache
-        }
-
-        protected void initializeValues(int[] values) {
-            assert(assertCanChangeLength(this));
-            assert(length == 0);
-            this.values = values;
-            this.length = values.length;
-        }
-
-        /** Collect one value, or store one decoded value. */
-        protected void addValue(int x) {
-            assert(assertCanChangeLength(this));
-            if (length == values.length)
-                setCapacity(length < 1000 ? length * 10 : length * 2);
-            values[length++] = x;
-        }
-
-        private boolean canVaryCoding() {
-            if (!optVaryCodings)           return false;
-            if (length == 0)               return false;
-            // Can't read band_headers w/o the archive header:
-            if (this == archive_header_0)  return false;
-            if (this == archive_header_S)  return false;
-            if (this == archive_header_1)  return false;
-            // BYTE1 bands can't vary codings, but the others can.
-            // All that's needed for the initial escape is at least
-            // 256 negative values or more than 256 non-negative values
-            return (regularCoding.min() <= -256 || regularCoding.max() >= 256);
-        }
-
-        private boolean shouldVaryCoding() {
-            assert(canVaryCoding());
-            if (effort < MAX_EFFORT && length < SHORT_BAND_HEURISTIC)
-                return false;
-            return true;
-        }
-
-        @Override
-        protected void chooseBandCodings() throws IOException {
-            boolean canVary = canVaryCoding();
-            if (!canVary || !shouldVaryCoding()) {
-                if (regularCoding.canRepresent(values, 0, length)) {
-                    bandCoding = regularCoding;
-                } else {
-                    assert(canVary);
-                    if (verbose > 1)
-                        Utils.log.fine("regular coding fails in band "+name());
-                    bandCoding = UNSIGNED5;
-                }
-                outputSize = -1;
-            } else {
-                int[] sizes = {0,0};
-                bandCoding = chooseCoding(values, 0, length,
-                                          regularCoding, name(),
-                                          sizes);
-                outputSize = sizes[CodingChooser.BYTE_SIZE];
-                if (outputSize == 0)  // CodingChooser failed to size it.
-                    outputSize = -1;
-            }
-
-            // Compute and save the meta-coding bytes also.
-            if (bandCoding != regularCoding) {
-                metaCoding = bandCoding.getMetaCoding(regularCoding);
-                if (verbose > 1) {
-                    Utils.log.fine("alternate coding "+this+" "+bandCoding);
-                }
-            } else if (canVary &&
-                       decodeEscapeValue(values[0], regularCoding) >= 0) {
-                // Need an explicit default.
-                metaCoding = defaultMetaCoding;
-            } else {
-                // Common case:  Zero bytes of meta coding.
-                metaCoding = noMetaCoding;
-            }
-            if (metaCoding.length > 0
-                && (verbose > 2 || verbose > 1 && metaCoding.length > 1)) {
-                StringBuilder sb = new StringBuilder();
-                for (int i = 0; i < metaCoding.length; i++) {
-                    if (i == 1)  sb.append(" /");
-                    sb.append(" ").append(metaCoding[i] & 0xFF);
-                }
-                Utils.log.fine("   meta-coding "+sb);
-            }
-
-            assert((outputSize < 0) ||
-                   !(bandCoding instanceof Coding) ||
-                   (outputSize == ((Coding)bandCoding)
-                    .getLength(values, 0, length)))
-                : (bandCoding+" : "+
-                   outputSize+" != "+
-                   ((Coding)bandCoding).getLength(values, 0, length)
-                   +" ?= "+getCodingChooser().computeByteSize(bandCoding,values,0,length)
-                   );
-
-            // Compute outputSize of the escape value X, if any.
-            if (metaCoding.length > 0) {
-                // First byte XB of meta-coding is treated specially,
-                // but any other bytes go into the band headers band.
-                // This must be done before any other output happens.
-                if (outputSize >= 0)
-                    outputSize += computeEscapeSize();  // good cache
-                // Other bytes go into band_headers.
-                for (int i = 1; i < metaCoding.length; i++) {
-                    band_headers.putByte(metaCoding[i] & 0xFF);
-                }
-            }
-        }
-
-        @Override
-        protected long computeOutputSize() {
-            outputSize = getCodingChooser().computeByteSize(bandCoding,
-                                                            values, 0, length);
-            assert(outputSize < Integer.MAX_VALUE);
-            outputSize += computeEscapeSize();
-            return outputSize;
-        }
-
-        protected int computeEscapeSize() {
-            if (metaCoding.length == 0)  return 0;
-            int XB = metaCoding[0] & 0xFF;
-            int X = encodeEscapeValue(XB, regularCoding);
-            return regularCoding.setD(0).getLength(X);
-        }
-
-        @Override
-        protected void writeDataTo(OutputStream out) throws IOException {
-            if (length == 0)  return;  // nothing to write
-            long len0 = 0;
-            if (out == outputCounter) {
-                len0 = outputCounter.getCount();
-            }
-            if (metaCoding.length > 0) {
-                int XB = metaCoding[0] & 0xFF;
-                // We need an explicit band header, either because
-                // there is a non-default coding method, or because
-                // the first value would be parsed as an escape value.
-                int X = encodeEscapeValue(XB, regularCoding);
-                //System.out.println("X="+X+" XB="+XB+" in "+this);
-                regularCoding.setD(0).writeTo(out, X);
-            }
-            bandCoding.writeArrayTo(out, values, 0, length);
-            if (out == outputCounter) {
-                assert(outputSize == outputCounter.getCount() - len0)
-                    : (outputSize+" != "+outputCounter.getCount()+"-"+len0);
-            }
-            if (optDumpBands)  dumpBand();
-        }
-
-        @Override
-        protected void readDataFrom(InputStream in) throws IOException {
-            length = valuesExpected();
-            if (length == 0)  return;  // nothing to read
-            if (verbose > 1)
-                Utils.log.fine("Reading band "+this);
-            if (!canVaryCoding()) {
-                bandCoding = regularCoding;
-                metaCoding = noMetaCoding;
-            } else {
-                assert(in.markSupported());  // input must be buffered
-                in.mark(Coding.B_MAX);
-                int X = regularCoding.setD(0).readFrom(in);
-                int XB = decodeEscapeValue(X, regularCoding);
-                if (XB < 0) {
-                    // Do not consume this value.  No alternate coding.
-                    in.reset();
-                    bandCoding = regularCoding;
-                    metaCoding = noMetaCoding;
-                } else if (XB == _meta_default) {
-                    bandCoding = regularCoding;
-                    metaCoding = defaultMetaCoding;
-                } else {
-                    if (verbose > 2)
-                        Utils.log.fine("found X="+X+" => XB="+XB);
-                    bandCoding = getBandHeader(XB, regularCoding);
-                    // This is really used only by dumpBands.
-                    int p0 = bandHeaderBytePos0;
-                    int p1 = bandHeaderBytePos;
-                    metaCoding = new byte[p1-p0];
-                    System.arraycopy(bandHeaderBytes, p0,
-                                     metaCoding, 0, metaCoding.length);
-                }
-            }
-            if (bandCoding != regularCoding) {
-                if (verbose > 1)
-                    Utils.log.fine(name()+": irregular coding "+bandCoding);
-            }
-            bandCoding.readArrayFrom(in, values, 0, length);
-            if (optDumpBands)  dumpBand();
-        }
-
-        @Override
-        public void doneDisbursing() {
-            super.doneDisbursing();
-            values = null;  // for GC
-        }
-
-        private void dumpBand() throws IOException {
-            assert(optDumpBands);
-            try (PrintStream ps = new PrintStream(getDumpStream(this, ".txt"))) {
-                String irr = (bandCoding == regularCoding) ? "" : " irregular";
-                ps.print("# length="+length+
-                         " size="+outputSize()+
-                         irr+" coding="+bandCoding);
-                if (metaCoding != noMetaCoding) {
-                    StringBuilder sb = new StringBuilder();
-                    for (int i = 0; i < metaCoding.length; i++) {
-                        if (i == 1)  sb.append(" /");
-                        sb.append(" ").append(metaCoding[i] & 0xFF);
-                    }
-                    ps.print(" //header: "+sb);
-                }
-                printArrayTo(ps, values, 0, length);
-            }
-            try (OutputStream ds = getDumpStream(this, ".bnd")) {
-                bandCoding.writeArrayTo(ds, values, 0, length);
-            }
-        }
-
-        /** Disburse one value. */
-        protected int getValue() {
-            assert(phase() == DISBURSE_PHASE);
-            // when debugging return a zero if lengths are zero
-            if (optDebugBands && length == 0 && valuesDisbursed == length)
-                return 0;
-            assert(valuesDisbursed <= length);
-            return values[valuesDisbursed++];
-        }
-
-        /** Reset for another pass over the same value set. */
-        public void resetForSecondPass() {
-            assert(phase() == DISBURSE_PHASE);
-            assert(valuesDisbursed == length());  // 1st pass is complete
-            valuesDisbursed = 0;
-        }
-    }
-
-    class ByteBand extends Band {
-        private ByteArrayOutputStream bytes;  // input buffer
-        private ByteArrayOutputStream bytesForDump;
-        private InputStream in;
-
-        public ByteBand(String name) {
-            super(name, BYTE1);
-        }
-
-        @Override
-        public int capacity() {
-            return bytes == null ? -1 : Integer.MAX_VALUE;
-        }
-        @Override
-        protected void setCapacity(int cap) {
-            assert(bytes == null);  // do this just once
-            bytes = new ByteArrayOutputStream(cap);
-        }
-        public void destroy() {
-            lengthForDebug = length();
-            bytes = null;
-        }
-
-        @Override
-        public int length() {
-            return bytes == null ? -1 : bytes.size();
-        }
-        public void reset() {
-            bytes.reset();
-        }
-        @Override
-        protected int valuesRemainingForDebug() {
-            return (bytes == null) ? -1 : ((ByteArrayInputStream)in).available();
-        }
-
-        @Override
-        protected void chooseBandCodings() throws IOException {
-            // No-op.
-            assert(decodeEscapeValue(regularCoding.min(), regularCoding) < 0);
-            assert(decodeEscapeValue(regularCoding.max(), regularCoding) < 0);
-        }
-
-        @Override
-        protected long computeOutputSize() {
-            // do not cache
-            return bytes.size();
-        }
-
-        @Override
-        public void writeDataTo(OutputStream out) throws IOException {
-            if (length() == 0)  return;
-            bytes.writeTo(out);
-            if (optDumpBands)  dumpBand();
-            destroy();  // done with the bits!
-        }
-
-        private void dumpBand() throws IOException {
-            assert(optDumpBands);
-            try (OutputStream ds = getDumpStream(this, ".bnd")) {
-                if (bytesForDump != null)
-                    bytesForDump.writeTo(ds);
-                else
-                    bytes.writeTo(ds);
-            }
-        }
-
-        @Override
-        public void readDataFrom(InputStream in) throws IOException {
-            int vex = valuesExpected();
-            if (vex == 0)  return;
-            if (verbose > 1) {
-                lengthForDebug = vex;
-                Utils.log.fine("Reading band "+this);
-                lengthForDebug = -1;
-            }
-            byte[] buf = new byte[Math.min(vex, 1<<14)];
-            while (vex > 0) {
-                int nr = in.read(buf, 0, Math.min(vex, buf.length));
-                if (nr < 0)  throw new EOFException();
-                bytes.write(buf, 0, nr);
-                vex -= nr;
-            }
-            if (optDumpBands)  dumpBand();
-        }
-
-        @Override
-        public void readyToDisburse() {
-            in = new ByteArrayInputStream(bytes.toByteArray());
-            super.readyToDisburse();
-        }
-
-        @Override
-        public void doneDisbursing() {
-            super.doneDisbursing();
-            if (optDumpBands
-                && bytesForDump != null && bytesForDump.size() > 0) {
-                try {
-                    dumpBand();
-                } catch (IOException ee) {
-                    throw new RuntimeException(ee);
-                }
-            }
-            in = null; // GC
-            bytes = null;  // GC
-            bytesForDump = null;  // GC
-        }
-
-        // alternative to readFrom:
-        public void setInputStreamFrom(InputStream in) throws IOException {
-            assert(bytes == null);
-            assert(assertReadyToReadFrom(this, in));
-            setPhase(READ_PHASE);
-            this.in = in;
-            if (optDumpBands) {
-                // Tap the stream.
-                bytesForDump = new ByteArrayOutputStream();
-                this.in = new FilterInputStream(in) {
-                    @Override
-                    public int read() throws IOException {
-                        int ch = in.read();
-                        if (ch >= 0)  bytesForDump.write(ch);
-                        return ch;
-                    }
-                    @Override
-                    public int read(byte b[], int off, int len) throws IOException {
-                        int nr = in.read(b, off, len);
-                        if (nr >= 0)  bytesForDump.write(b, off, nr);
-                        return nr;
-                    }
-                };
-            }
-            super.readyToDisburse();
-        }
-
-        public OutputStream collectorStream() {
-            assert(phase() == COLLECT_PHASE);
-            assert(bytes != null);
-            return bytes;
-        }
-
-        public InputStream getInputStream() {
-            assert(phase() == DISBURSE_PHASE);
-            assert(in != null);
-            return in;
-        }
-        public int getByte() throws IOException {
-            int b = getInputStream().read();
-            if (b < 0)  throw new EOFException();
-            return b;
-        }
-        public void putByte(int b) throws IOException {
-            assert(b == (b & 0xFF));
-            collectorStream().write(b);
-        }
-        @Override
-        public String toString() {
-            return "byte "+super.toString();
-        }
-    }
-
-    class IntBand extends ValueBand {
-        // The usual coding for bands is 7bit/5byte/delta.
-        public IntBand(String name, Coding regularCoding) {
-            super(name, regularCoding);
-        }
-
-        public void putInt(int x) {
-            assert(phase() == COLLECT_PHASE);
-            addValue(x);
-        }
-
-        public int getInt() {
-            return getValue();
-        }
-        /** Return the sum of all values in this band. */
-        public int getIntTotal() {
-            assert(phase() == DISBURSE_PHASE);
-            // assert that this is the whole pass; no other reads allowed
-            assert(valuesRemainingForDebug() == length());
-            int total = 0;
-            for (int k = length(); k > 0; k--) {
-                total += getInt();
-            }
-            resetForSecondPass();
-            return total;
-        }
-        /** Return the occurrence count of a specific value in this band. */
-        public int getIntCount(int value) {
-            assert(phase() == DISBURSE_PHASE);
-            // assert that this is the whole pass; no other reads allowed
-            assert(valuesRemainingForDebug() == length());
-            int total = 0;
-            for (int k = length(); k > 0; k--) {
-                if (getInt() == value) {
-                    total += 1;
-                }
-            }
-            resetForSecondPass();
-            return total;
-        }
-    }
-
-    static int getIntTotal(int[] values) {
-        int total = 0;
-        for (int i = 0; i < values.length; i++) {
-            total += values[i];
-        }
-        return total;
-    }
-
-    class CPRefBand extends ValueBand {
-        Index index;
-        boolean nullOK;
-
-        public CPRefBand(String name, Coding regularCoding, byte cpTag, boolean nullOK) {
-            super(name, regularCoding);
-            this.nullOK = nullOK;
-            if (cpTag != CONSTANT_None)
-                setBandIndex(this, cpTag);
-        }
-        public CPRefBand(String name, Coding regularCoding, byte cpTag) {
-            this(name, regularCoding, cpTag, false);
-        }
-        public CPRefBand(String name, Coding regularCoding, Object undef) {
-            this(name, regularCoding, CONSTANT_None, false);
-        }
-
-        public void setIndex(Index index) {
-            this.index = index;
-        }
-
-        protected void readDataFrom(InputStream in) throws IOException {
-            super.readDataFrom(in);
-            assert(assertValidCPRefs(this));
-        }
-
-        /** Write a constant pool reference. */
-        public void putRef(Entry e) {
-            addValue(encodeRefOrNull(e, index));
-        }
-        public void putRef(Entry e, Index index) {
-            assert(this.index == null);
-            addValue(encodeRefOrNull(e, index));
-        }
-        public void putRef(Entry e, byte cptag) {
-            putRef(e, getCPIndex(cptag));
-        }
-
-        public Entry getRef() {
-            if (index == null)  Utils.log.warning("No index for "+this);
-            assert(index != null);
-            return decodeRefOrNull(getValue(), index);
-        }
-        public Entry getRef(Index index) {
-            assert(this.index == null);
-            return decodeRefOrNull(getValue(), index);
-        }
-        public Entry getRef(byte cptag) {
-            return getRef(getCPIndex(cptag));
-        }
-
-        private int encodeRefOrNull(Entry e, Index index) {
-            int nonNullCode;  // NNC is the coding which assumes nulls are rare
-            if (e == null) {
-                nonNullCode = -1;  // negative values are rare
-            } else {
-                nonNullCode = encodeRef(e, index);
-            }
-            // If nulls are expected, increment, to make -1 code turn to 0.
-            return (nullOK ? 1 : 0) + nonNullCode;
-        }
-        private Entry decodeRefOrNull(int code, Index index) {
-            // Inverse to encodeRefOrNull...
-            int nonNullCode = code - (nullOK ? 1 : 0);
-            if (nonNullCode == -1) {
-                return null;
-            } else {
-                return decodeRef(nonNullCode, index);
-            }
-        }
-    }
-
-    // Bootstrap support for CPRefBands.  These are needed to record
-    // intended CP indexes, before the CP has been created.
-    private final List<CPRefBand> allKQBands = new ArrayList<>();
-    private List<Object[]> needPredefIndex = new ArrayList<>();
-
-
-    int encodeRef(Entry e, Index ix) {
-        if (ix == null)
-            throw new RuntimeException("null index for " + e.stringValue());
-        int coding = ix.indexOf(e);
-        if (verbose > 2)
-            Utils.log.fine("putRef "+coding+" => "+e);
-        return coding;
-    }
-
-    Entry decodeRef(int n, Index ix) {
-        if (n < 0 || n >= ix.size())
-            Utils.log.warning("decoding bad ref "+n+" in "+ix);
-        Entry e = ix.getEntry(n);
-        if (verbose > 2)
-            Utils.log.fine("getRef "+n+" => "+e);
-        return e;
-    }
-
-    private CodingChooser codingChooser;
-    protected CodingChooser getCodingChooser() {
-        if (codingChooser == null) {
-            codingChooser = new CodingChooser(effort, basicCodings);
-            if (codingChooser.stress != null
-                && this instanceof PackageWriter) {
-                // Twist the random state based on my first file.
-                // This sends each segment off in a different direction.
-                List<Package.Class> classes = ((PackageWriter)this).pkg.classes;
-                if (!classes.isEmpty()) {
-                    Package.Class cls = classes.get(0);
-                    codingChooser.addStressSeed(cls.getName().hashCode());
-                }
-            }
-        }
-        return codingChooser;
-    }
-
-    public CodingMethod chooseCoding(int[] values, int start, int end,
-                                     Coding regular, String bandName,
-                                     int[] sizes) {
-        assert(optVaryCodings);
-        if (effort <= MIN_EFFORT) {
-            return regular;
-        }
-        CodingChooser cc = getCodingChooser();
-        if (verbose > 1 || cc.verbose > 1) {
-            Utils.log.fine("--- chooseCoding "+bandName);
-        }
-        return cc.choose(values, start, end, regular, sizes);
-    }
-
-    static final byte[] defaultMetaCoding = { _meta_default };
-    static final byte[] noMetaCoding      = {};
-
-    // The first value in a band is always coded with the default coding D.
-    // If this first value X is an escape value, it actually represents the
-    // first (and perhaps only) byte of a meta-coding.
-    //
-    // If D.S != 0 and D includes the range [-256..-1],
-    // the escape values are in that range,
-    // and the first byte XB is -1-X.
-    //
-    // If D.S == 0 and D includes the range [(D.L)..(D.L)+255],
-    // the escape values are in that range,
-    // and XB is X-(D.L).
-    //
-    // This representation is designed so that a band header is unlikely
-    // to be confused with the initial value of a headerless band,
-    // and yet so that a band header is likely to occupy only a byte or two.
-    //
-    // Result is in [0..255] if XB was successfully extracted, else -1.
-    // See section "Coding Specifier Meta-Encoding" in the JSR 200 spec.
-    protected static int decodeEscapeValue(int X, Coding regularCoding) {
-        // The first value in a band is always coded with the default coding D.
-        // If this first value X is an escape value, it actually represents the
-        // first (and perhaps only) byte of a meta-coding.
-        // Result is in [0..255] if XB was successfully extracted, else -1.
-        if (regularCoding.B() == 1 || regularCoding.L() == 0)
-            return -1;  // degenerate regular coding (BYTE1)
-        if (regularCoding.S() != 0) {
-            if (-256 <= X && X <= -1 && regularCoding.min() <= -256) {
-                int XB = -1-X;
-                assert(XB >= 0 && XB < 256);
-                return XB;
-            }
-        } else {
-            int L = regularCoding.L();
-            if (L <= X && X <= L+255 && regularCoding.max() >= L+255) {
-                int XB = X-L;
-                assert(XB >= 0 && XB < 256);
-                return XB;
-            }
-        }
-        return -1;  // negative value for failure
-    }
-    // Inverse to decodeEscapeValue().
-    protected static int encodeEscapeValue(int XB, Coding regularCoding) {
-        assert(XB >= 0 && XB < 256);
-        assert(regularCoding.B() > 1 && regularCoding.L() > 0);
-        int X;
-        if (regularCoding.S() != 0) {
-            assert(regularCoding.min() <= -256);
-            X = -1-XB;
-        } else {
-            int L = regularCoding.L();
-            assert(regularCoding.max() >= L+255);
-            X = XB+L;
-        }
-        assert(decodeEscapeValue(X, regularCoding) == XB)
-            : (regularCoding+" XB="+XB+" X="+X);
-        return X;
-    }
-
-    static {
-        boolean checkXB = false;
-        assert(checkXB = true);
-        if (checkXB) {
-            for (int i = 0; i < basicCodings.length; i++) {
-                Coding D = basicCodings[i];
-                if (D == null)   continue;
-                if (D.B() == 1)  continue;
-                if (D.L() == 0)  continue;
-                for (int XB = 0; XB <= 255; XB++) {
-                    // The following exercises decodeEscapeValue also:
-                    encodeEscapeValue(XB, D);
-                }
-            }
-        }
-    }
-
-    class MultiBand extends Band {
-        MultiBand(String name, Coding regularCoding) {
-            super(name, regularCoding);
-        }
-
-        @Override
-        public Band init() {
-            super.init();
-            // This is all just to keep the asserts happy:
-            setCapacity(0);
-            if (phase() == EXPECT_PHASE) {
-                // Fast forward:
-                setPhase(READ_PHASE);
-                setPhase(DISBURSE_PHASE);
-            }
-            return this;
-        }
-
-        Band[] bands     = new Band[10];
-        int    bandCount = 0;
-
-        int size() {
-            return bandCount;
-        }
-        Band get(int i) {
-            assert(i < bandCount);
-            return bands[i];
-        }
-        Band[] toArray() {
-            return (Band[]) realloc(bands, bandCount);
-        }
-
-        void add(Band b) {
-            assert(bandCount == 0 || notePrevForAssert(b, bands[bandCount-1]));
-            if (bandCount == bands.length) {
-                bands = (Band[]) realloc(bands);
-            }
-            bands[bandCount++] = b;
-        }
-
-        ByteBand newByteBand(String name) {
-            ByteBand b = new ByteBand(name);
-            b.init(); add(b);
-            return b;
-        }
-        IntBand newIntBand(String name) {
-            IntBand b = new IntBand(name, regularCoding);
-            b.init(); add(b);
-            return b;
-        }
-        IntBand newIntBand(String name, Coding regularCoding) {
-            IntBand b = new IntBand(name, regularCoding);
-            b.init(); add(b);
-            return b;
-        }
-        MultiBand newMultiBand(String name, Coding regularCoding) {
-            MultiBand b = new MultiBand(name, regularCoding);
-            b.init(); add(b);
-            return b;
-        }
-        CPRefBand newCPRefBand(String name, byte cpTag) {
-            CPRefBand b = new CPRefBand(name, regularCoding, cpTag);
-            b.init(); add(b);
-            return b;
-        }
-        CPRefBand newCPRefBand(String name, Coding regularCoding,
-                               byte cpTag) {
-            CPRefBand b = new CPRefBand(name, regularCoding, cpTag);
-            b.init(); add(b);
-            return b;
-        }
-        CPRefBand newCPRefBand(String name, Coding regularCoding,
-                               byte cpTag, boolean nullOK) {
-            CPRefBand b = new CPRefBand(name, regularCoding, cpTag, nullOK);
-            b.init(); add(b);
-            return b;
-        }
-
-        int bandCount() { return bandCount; }
-
-        private int cap = -1;
-        @Override
-        public int capacity() { return cap; }
-        @Override
-        public void setCapacity(int cap) { this.cap = cap; }
-
-        @Override
-        public int length() { return 0; }
-        @Override
-        public int valuesRemainingForDebug() { return 0; }
-
-        @Override
-        protected void chooseBandCodings() throws IOException {
-            // coding decision pass
-            for (int i = 0; i < bandCount; i++) {
-                Band b = bands[i];
-                b.chooseBandCodings();
-            }
-        }
-
-        @Override
-        protected long computeOutputSize() {
-            // coding decision pass
-            long sum = 0;
-            for (int i = 0; i < bandCount; i++) {
-                Band b = bands[i];
-                long bsize = b.outputSize();
-                assert(bsize >= 0) : b;
-                sum += bsize;
-            }
-            // do not cache
-            return sum;
-        }
-
-        @Override
-        protected void writeDataTo(OutputStream out) throws IOException {
-            long preCount = 0;
-            if (outputCounter != null)  preCount = outputCounter.getCount();
-            for (int i = 0; i < bandCount; i++) {
-                Band b = bands[i];
-                b.writeTo(out);
-                if (outputCounter != null) {
-                    long postCount = outputCounter.getCount();
-                    long len = postCount - preCount;
-                    preCount = postCount;
-                    if ((verbose > 0 && len > 0) || verbose > 1) {
-                        Utils.log.info("  ...wrote "+len+" bytes from "+b);
-                    }
-                }
-            }
-        }
-
-        @Override
-        protected void readDataFrom(InputStream in) throws IOException {
-            assert(false);  // not called?
-            for (int i = 0; i < bandCount; i++) {
-                Band b = bands[i];
-                b.readFrom(in);
-                if ((verbose > 0 && b.length() > 0) || verbose > 1) {
-                    Utils.log.info("  ...read "+b);
-                }
-            }
-        }
-
-        @Override
-        public String toString() {
-            return "{"+bandCount()+" bands: "+super.toString()+"}";
-        }
-    }
-
-    /**
-     * An output stream which counts the number of bytes written.
-     */
-    private static
-    class ByteCounter extends FilterOutputStream {
-        // (should go public under the name CountingOutputStream?)
-
-        private long count;
-
-        public ByteCounter(OutputStream out) {
-            super(out);
-        }
-
-        public long getCount() { return count; }
-        public void setCount(long c) { count = c; }
-
-        @Override
-        public void write(int b) throws IOException {
-            count++;
-            if (out != null)  out.write(b);
-        }
-        @Override
-        public void write(byte b[], int off, int len) throws IOException {
-            count += len;
-            if (out != null)  out.write(b, off, len);
-        }
-        @Override
-        public String toString() {
-            return String.valueOf(getCount());
-        }
-    }
-    ByteCounter outputCounter;
-
-    void writeAllBandsTo(OutputStream out) throws IOException {
-        // Wrap a byte-counter around the output stream.
-        outputCounter = new ByteCounter(out);
-        out = outputCounter;
-        all_bands.writeTo(out);
-        if (verbose > 0) {
-            long nbytes = outputCounter.getCount();
-            Utils.log.info("Wrote total of "+nbytes+" bytes.");
-            assert(nbytes == archiveSize0+archiveSize1);
-        }
-        outputCounter = null;
-    }
-
-    // random AO_XXX bits, decoded from the archive header
-    protected int archiveOptions;
-
-    // archiveSize1 sizes most of the archive [archive_options..file_bits).
-    protected long archiveSize0; // size through archive_size_lo
-    protected long archiveSize1; // size reported in archive_header
-    protected int  archiveNextCount; // reported in archive_header
-
-    static final int AH_LENGTH_0 = 3;     // archive_header_0 = {minver, majver, options}
-    static final int AH_LENGTH_MIN = 15;  // observed in spec {header_0[3], cp_counts[8], class_counts[4]}
-    // Length contributions from optional archive size fields:
-    static final int AH_LENGTH_S = 2; // archive_header_S = optional {size_hi, size_lo}
-    static final int AH_ARCHIVE_SIZE_HI = 0; // offset in archive_header_S
-    static final int AH_ARCHIVE_SIZE_LO = 1; // offset in archive_header_S
-    // Length contributions from optional header fields:
-    static final int AH_FILE_HEADER_LEN = 5; // file_counts = {{size_hi, size_lo}, next, modtime, files}
-    static final int AH_SPECIAL_FORMAT_LEN = 2; // special_counts = {layouts, band_headers}
-    static final int AH_CP_NUMBER_LEN = 4;  // cp_number_counts = {int, float, long, double}
-    static final int AH_CP_EXTRA_LEN = 4;  // cp_attr_counts = {MH, MT, InDy, BSM}
-
-    // Common structure of attribute band groups:
-    static final int AB_FLAGS_HI = 0;
-    static final int AB_FLAGS_LO = 1;
-    static final int AB_ATTR_COUNT = 2;
-    static final int AB_ATTR_INDEXES = 3;
-    static final int AB_ATTR_CALLS = 4;
-
-    static IntBand getAttrBand(MultiBand xxx_attr_bands, int which) {
-        IntBand b = (IntBand) xxx_attr_bands.get(which);
-        switch (which) {
-        case AB_FLAGS_HI:
-            assert(b.name().endsWith("_flags_hi")); break;
-        case AB_FLAGS_LO:
-            assert(b.name().endsWith("_flags_lo")); break;
-        case AB_ATTR_COUNT:
-            assert(b.name().endsWith("_attr_count")); break;
-        case AB_ATTR_INDEXES:
-            assert(b.name().endsWith("_attr_indexes")); break;
-        case AB_ATTR_CALLS:
-            assert(b.name().endsWith("_attr_calls")); break;
-        default:
-            assert(false); break;
-        }
-        return b;
-    }
-
-    private static final boolean NULL_IS_OK = true;
-
-    MultiBand all_bands = (MultiBand) new MultiBand("(package)", UNSIGNED5).init();
-
-    // file header (various random bytes)
-    ByteBand archive_magic = all_bands.newByteBand("archive_magic");
-    IntBand  archive_header_0 = all_bands.newIntBand("archive_header_0", UNSIGNED5);
-    IntBand  archive_header_S = all_bands.newIntBand("archive_header_S", UNSIGNED5);
-    IntBand  archive_header_1 = all_bands.newIntBand("archive_header_1", UNSIGNED5);
-    ByteBand band_headers = all_bands.newByteBand("band_headers");
-
-    // constant pool contents
-    MultiBand cp_bands = all_bands.newMultiBand("(constant_pool)", DELTA5);
-    IntBand   cp_Utf8_prefix = cp_bands.newIntBand("cp_Utf8_prefix");
-    IntBand   cp_Utf8_suffix = cp_bands.newIntBand("cp_Utf8_suffix", UNSIGNED5);
-    IntBand   cp_Utf8_chars = cp_bands.newIntBand("cp_Utf8_chars", CHAR3);
-    IntBand   cp_Utf8_big_suffix = cp_bands.newIntBand("cp_Utf8_big_suffix");
-    MultiBand cp_Utf8_big_chars = cp_bands.newMultiBand("(cp_Utf8_big_chars)", DELTA5);
-    IntBand   cp_Int = cp_bands.newIntBand("cp_Int", UDELTA5);
-    IntBand   cp_Float = cp_bands.newIntBand("cp_Float", UDELTA5);
-    IntBand   cp_Long_hi = cp_bands.newIntBand("cp_Long_hi", UDELTA5);
-    IntBand   cp_Long_lo = cp_bands.newIntBand("cp_Long_lo");
-    IntBand   cp_Double_hi = cp_bands.newIntBand("cp_Double_hi", UDELTA5);
-    IntBand   cp_Double_lo = cp_bands.newIntBand("cp_Double_lo");
-    CPRefBand cp_String = cp_bands.newCPRefBand("cp_String", UDELTA5, CONSTANT_Utf8);
-    CPRefBand cp_Class = cp_bands.newCPRefBand("cp_Class", UDELTA5, CONSTANT_Utf8);
-    CPRefBand cp_Signature_form = cp_bands.newCPRefBand("cp_Signature_form", CONSTANT_Utf8);
-    CPRefBand cp_Signature_classes = cp_bands.newCPRefBand("cp_Signature_classes", UDELTA5, CONSTANT_Class);
-    CPRefBand cp_Descr_name = cp_bands.newCPRefBand("cp_Descr_name", CONSTANT_Utf8);
-    CPRefBand cp_Descr_type = cp_bands.newCPRefBand("cp_Descr_type", UDELTA5, CONSTANT_Signature);
-    CPRefBand cp_Field_class = cp_bands.newCPRefBand("cp_Field_class", CONSTANT_Class);
-    CPRefBand cp_Field_desc = cp_bands.newCPRefBand("cp_Field_desc", UDELTA5, CONSTANT_NameandType);
-    CPRefBand cp_Method_class = cp_bands.newCPRefBand("cp_Method_class", CONSTANT_Class);
-    CPRefBand cp_Method_desc = cp_bands.newCPRefBand("cp_Method_desc", UDELTA5, CONSTANT_NameandType);
-    CPRefBand cp_Imethod_class = cp_bands.newCPRefBand("cp_Imethod_class", CONSTANT_Class);
-    CPRefBand cp_Imethod_desc = cp_bands.newCPRefBand("cp_Imethod_desc", UDELTA5, CONSTANT_NameandType);
-    IntBand   cp_MethodHandle_refkind = cp_bands.newIntBand("cp_MethodHandle_refkind", DELTA5);
-    CPRefBand cp_MethodHandle_member = cp_bands.newCPRefBand("cp_MethodHandle_member", UDELTA5, CONSTANT_AnyMember);
-    CPRefBand cp_MethodType = cp_bands.newCPRefBand("cp_MethodType", UDELTA5, CONSTANT_Signature);
-    CPRefBand cp_BootstrapMethod_ref = cp_bands.newCPRefBand("cp_BootstrapMethod_ref", DELTA5, CONSTANT_MethodHandle);
-    IntBand   cp_BootstrapMethod_arg_count = cp_bands.newIntBand("cp_BootstrapMethod_arg_count", UDELTA5);
-    CPRefBand cp_BootstrapMethod_arg = cp_bands.newCPRefBand("cp_BootstrapMethod_arg", DELTA5, CONSTANT_LoadableValue);
-    CPRefBand cp_InvokeDynamic_spec = cp_bands.newCPRefBand("cp_InvokeDynamic_spec", DELTA5, CONSTANT_BootstrapMethod);
-    CPRefBand cp_InvokeDynamic_desc = cp_bands.newCPRefBand("cp_InvokeDynamic_desc", UDELTA5, CONSTANT_NameandType);
-
-    // bands for carrying attribute definitions:
-    MultiBand attr_definition_bands = all_bands.newMultiBand("(attr_definition_bands)", UNSIGNED5);
-    ByteBand attr_definition_headers = attr_definition_bands.newByteBand("attr_definition_headers");
-    CPRefBand attr_definition_name = attr_definition_bands.newCPRefBand("attr_definition_name", CONSTANT_Utf8);
-    CPRefBand attr_definition_layout = attr_definition_bands.newCPRefBand("attr_definition_layout", CONSTANT_Utf8);
-
-    // bands for hardwired InnerClasses attribute (shared across the package)
-    MultiBand ic_bands = all_bands.newMultiBand("(ic_bands)", DELTA5);
-    CPRefBand ic_this_class = ic_bands.newCPRefBand("ic_this_class", UDELTA5, CONSTANT_Class);
-    IntBand ic_flags = ic_bands.newIntBand("ic_flags", UNSIGNED5);
-    // These bands contain data only where flags sets ACC_IC_LONG_FORM:
-    CPRefBand ic_outer_class = ic_bands.newCPRefBand("ic_outer_class", DELTA5, CONSTANT_Class, NULL_IS_OK);
-    CPRefBand ic_name = ic_bands.newCPRefBand("ic_name", DELTA5, CONSTANT_Utf8, NULL_IS_OK);
-
-    // bands for carrying class schema information:
-    MultiBand class_bands = all_bands.newMultiBand("(class_bands)", DELTA5);
-    CPRefBand class_this = class_bands.newCPRefBand("class_this", CONSTANT_Class);
-    CPRefBand class_super = class_bands.newCPRefBand("class_super", CONSTANT_Class);
-    IntBand   class_interface_count = class_bands.newIntBand("class_interface_count");
-    CPRefBand class_interface = class_bands.newCPRefBand("class_interface", CONSTANT_Class);
-
-    // bands for class members
-    IntBand   class_field_count = class_bands.newIntBand("class_field_count");
-    IntBand   class_method_count = class_bands.newIntBand("class_method_count");
-
-    CPRefBand field_descr = class_bands.newCPRefBand("field_descr", CONSTANT_NameandType);
-    MultiBand field_attr_bands = class_bands.newMultiBand("(field_attr_bands)", UNSIGNED5);
-    IntBand field_flags_hi = field_attr_bands.newIntBand("field_flags_hi");
-    IntBand field_flags_lo = field_attr_bands.newIntBand("field_flags_lo");
-    IntBand field_attr_count = field_attr_bands.newIntBand("field_attr_count");
-    IntBand field_attr_indexes = field_attr_bands.newIntBand("field_attr_indexes");
-    IntBand field_attr_calls = field_attr_bands.newIntBand("field_attr_calls");
-
-    // bands for predefined field attributes
-    CPRefBand field_ConstantValue_KQ = field_attr_bands.newCPRefBand("field_ConstantValue_KQ", CONSTANT_FieldSpecific);
-    CPRefBand field_Signature_RS = field_attr_bands.newCPRefBand("field_Signature_RS", CONSTANT_Signature);
-    MultiBand field_metadata_bands = field_attr_bands.newMultiBand("(field_metadata_bands)", UNSIGNED5);
-    MultiBand field_type_metadata_bands = field_attr_bands.newMultiBand("(field_type_metadata_bands)", UNSIGNED5);
-
-    CPRefBand method_descr = class_bands.newCPRefBand("method_descr", MDELTA5, CONSTANT_NameandType);
-    MultiBand method_attr_bands = class_bands.newMultiBand("(method_attr_bands)", UNSIGNED5);
-    IntBand  method_flags_hi = method_attr_bands.newIntBand("method_flags_hi");
-    IntBand  method_flags_lo = method_attr_bands.newIntBand("method_flags_lo");
-    IntBand  method_attr_count = method_attr_bands.newIntBand("method_attr_count");
-    IntBand  method_attr_indexes = method_attr_bands.newIntBand("method_attr_indexes");
-    IntBand  method_attr_calls = method_attr_bands.newIntBand("method_attr_calls");
-    // band for predefined method attributes
-    IntBand  method_Exceptions_N = method_attr_bands.newIntBand("method_Exceptions_N");
-    CPRefBand method_Exceptions_RC = method_attr_bands.newCPRefBand("method_Exceptions_RC", CONSTANT_Class);
-    CPRefBand method_Signature_RS = method_attr_bands.newCPRefBand("method_Signature_RS", CONSTANT_Signature);
-    MultiBand method_metadata_bands = method_attr_bands.newMultiBand("(method_metadata_bands)", UNSIGNED5);
-    // band for predefine method parameters
-    IntBand  method_MethodParameters_NB = method_attr_bands.newIntBand("method_MethodParameters_NB", BYTE1);
-    CPRefBand method_MethodParameters_name_RUN = method_attr_bands.newCPRefBand("method_MethodParameters_name_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK);
-    IntBand   method_MethodParameters_flag_FH = method_attr_bands.newIntBand("method_MethodParameters_flag_FH");
-    MultiBand method_type_metadata_bands = method_attr_bands.newMultiBand("(method_type_metadata_bands)", UNSIGNED5);
-
-    MultiBand class_attr_bands = class_bands.newMultiBand("(class_attr_bands)", UNSIGNED5);
-    IntBand class_flags_hi = class_attr_bands.newIntBand("class_flags_hi");
-    IntBand class_flags_lo = class_attr_bands.newIntBand("class_flags_lo");
-    IntBand class_attr_count = class_attr_bands.newIntBand("class_attr_count");
-    IntBand class_attr_indexes = class_attr_bands.newIntBand("class_attr_indexes");
-    IntBand class_attr_calls = class_attr_bands.newIntBand("class_attr_calls");
-    // band for predefined SourceFile and other class attributes
-    CPRefBand class_SourceFile_RUN = class_attr_bands.newCPRefBand("class_SourceFile_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK);
-    CPRefBand class_EnclosingMethod_RC = class_attr_bands.newCPRefBand("class_EnclosingMethod_RC", CONSTANT_Class);
-    CPRefBand class_EnclosingMethod_RDN = class_attr_bands.newCPRefBand("class_EnclosingMethod_RDN", UNSIGNED5, CONSTANT_NameandType, NULL_IS_OK);
-    CPRefBand class_Signature_RS = class_attr_bands.newCPRefBand("class_Signature_RS", CONSTANT_Signature);
-    MultiBand class_metadata_bands = class_attr_bands.newMultiBand("(class_metadata_bands)", UNSIGNED5);
-    IntBand   class_InnerClasses_N = class_attr_bands.newIntBand("class_InnerClasses_N");
-    CPRefBand class_InnerClasses_RC = class_attr_bands.newCPRefBand("class_InnerClasses_RC", CONSTANT_Class);
-    IntBand   class_InnerClasses_F = class_attr_bands.newIntBand("class_InnerClasses_F");
-    CPRefBand class_InnerClasses_outer_RCN = class_attr_bands.newCPRefBand("class_InnerClasses_outer_RCN", UNSIGNED5, CONSTANT_Class, NULL_IS_OK);
-    CPRefBand class_InnerClasses_name_RUN = class_attr_bands.newCPRefBand("class_InnerClasses_name_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK);
-    IntBand class_ClassFile_version_minor_H = class_attr_bands.newIntBand("class_ClassFile_version_minor_H");
-    IntBand class_ClassFile_version_major_H = class_attr_bands.newIntBand("class_ClassFile_version_major_H");
-    MultiBand class_type_metadata_bands = class_attr_bands.newMultiBand("(class_type_metadata_bands)", UNSIGNED5);
-
-    MultiBand code_bands = class_bands.newMultiBand("(code_bands)", UNSIGNED5);
-    ByteBand  code_headers = code_bands.newByteBand("code_headers"); //BYTE1
-    IntBand   code_max_stack = code_bands.newIntBand("code_max_stack", UNSIGNED5);
-    IntBand   code_max_na_locals = code_bands.newIntBand("code_max_na_locals", UNSIGNED5);
-    IntBand   code_handler_count = code_bands.newIntBand("code_handler_count", UNSIGNED5);
-    IntBand   code_handler_start_P = code_bands.newIntBand("code_handler_start_P", BCI5);
-    IntBand   code_handler_end_PO = code_bands.newIntBand("code_handler_end_PO", BRANCH5);
-    IntBand   code_handler_catch_PO = code_bands.newIntBand("code_handler_catch_PO", BRANCH5);
-    CPRefBand code_handler_class_RCN = code_bands.newCPRefBand("code_handler_class_RCN", UNSIGNED5, CONSTANT_Class, NULL_IS_OK);
-
-    MultiBand code_attr_bands = class_bands.newMultiBand("(code_attr_bands)", UNSIGNED5);
-    IntBand   code_flags_hi = code_attr_bands.newIntBand("code_flags_hi");
-    IntBand   code_flags_lo = code_attr_bands.newIntBand("code_flags_lo");
-    IntBand   code_attr_count = code_attr_bands.newIntBand("code_attr_count");
-    IntBand   code_attr_indexes = code_attr_bands.newIntBand("code_attr_indexes");
-    IntBand   code_attr_calls = code_attr_bands.newIntBand("code_attr_calls");
-
-    MultiBand stackmap_bands = code_attr_bands.newMultiBand("(StackMapTable_bands)", UNSIGNED5);
-    IntBand   code_StackMapTable_N = stackmap_bands.newIntBand("code_StackMapTable_N");
-    IntBand   code_StackMapTable_frame_T = stackmap_bands.newIntBand("code_StackMapTable_frame_T",BYTE1);
-    IntBand   code_StackMapTable_local_N = stackmap_bands.newIntBand("code_StackMapTable_local_N");
-    IntBand   code_StackMapTable_stack_N = stackmap_bands.newIntBand("code_StackMapTable_stack_N");
-    IntBand   code_StackMapTable_offset = stackmap_bands.newIntBand("code_StackMapTable_offset", UNSIGNED5);
-    IntBand   code_StackMapTable_T = stackmap_bands.newIntBand("code_StackMapTable_T", BYTE1);
-    CPRefBand code_StackMapTable_RC = stackmap_bands.newCPRefBand("code_StackMapTable_RC", CONSTANT_Class);
-    IntBand   code_StackMapTable_P = stackmap_bands.newIntBand("code_StackMapTable_P", BCI5);
-
-    // bands for predefined LineNumberTable attribute
-    IntBand   code_LineNumberTable_N = code_attr_bands.newIntBand("code_LineNumberTable_N");
-    IntBand   code_LineNumberTable_bci_P = code_attr_bands.newIntBand("code_LineNumberTable_bci_P", BCI5);
-    IntBand   code_LineNumberTable_line = code_attr_bands.newIntBand("code_LineNumberTable_line");
-
-    // bands for predefined LocalVariable{Type}Table attributes
-    IntBand   code_LocalVariableTable_N = code_attr_bands.newIntBand("code_LocalVariableTable_N");
-    IntBand   code_LocalVariableTable_bci_P = code_attr_bands.newIntBand("code_LocalVariableTable_bci_P", BCI5);
-    IntBand   code_LocalVariableTable_span_O = code_attr_bands.newIntBand("code_LocalVariableTable_span_O", BRANCH5);
-    CPRefBand code_LocalVariableTable_name_RU = code_attr_bands.newCPRefBand("code_LocalVariableTable_name_RU", CONSTANT_Utf8);
-    CPRefBand code_LocalVariableTable_type_RS = code_attr_bands.newCPRefBand("code_LocalVariableTable_type_RS", CONSTANT_Signature);
-    IntBand   code_LocalVariableTable_slot = code_attr_bands.newIntBand("code_LocalVariableTable_slot");
-    IntBand   code_LocalVariableTypeTable_N = code_attr_bands.newIntBand("code_LocalVariableTypeTable_N");
-    IntBand   code_LocalVariableTypeTable_bci_P = code_attr_bands.newIntBand("code_LocalVariableTypeTable_bci_P", BCI5);
-    IntBand   code_LocalVariableTypeTable_span_O = code_attr_bands.newIntBand("code_LocalVariableTypeTable_span_O", BRANCH5);
-    CPRefBand code_LocalVariableTypeTable_name_RU = code_attr_bands.newCPRefBand("code_LocalVariableTypeTable_name_RU", CONSTANT_Utf8);
-    CPRefBand code_LocalVariableTypeTable_type_RS = code_attr_bands.newCPRefBand("code_LocalVariableTypeTable_type_RS", CONSTANT_Signature);
-    IntBand   code_LocalVariableTypeTable_slot = code_attr_bands.newIntBand("code_LocalVariableTypeTable_slot");
-    MultiBand code_type_metadata_bands = code_attr_bands.newMultiBand("(code_type_metadata_bands)", UNSIGNED5);
-
-    // bands for bytecodes
-    MultiBand bc_bands = all_bands.newMultiBand("(byte_codes)", UNSIGNED5);
-    ByteBand  bc_codes = bc_bands.newByteBand("bc_codes"); //BYTE1
-    // remaining bands provide typed opcode fields required by the bc_codes
-
-    IntBand   bc_case_count = bc_bands.newIntBand("bc_case_count");  // *switch
-    IntBand   bc_case_value = bc_bands.newIntBand("bc_case_value", DELTA5);  // *switch
-    ByteBand  bc_byte = bc_bands.newByteBand("bc_byte"); //BYTE1   // bipush, iinc, *newarray
-    IntBand   bc_short = bc_bands.newIntBand("bc_short", DELTA5);  // sipush, wide iinc
-    IntBand   bc_local = bc_bands.newIntBand("bc_local");    // *load, *store, iinc, ret
-    IntBand   bc_label = bc_bands.newIntBand("bc_label", BRANCH5);    // if*, goto*, jsr*, *switch
-
-    // Most CP refs exhibit some correlation, and benefit from delta coding.
-    // The notable exceptions are class and method references.
-
-    // ldc* operands:
-    CPRefBand bc_intref = bc_bands.newCPRefBand("bc_intref", DELTA5, CONSTANT_Integer);
-    CPRefBand bc_floatref = bc_bands.newCPRefBand("bc_floatref", DELTA5, CONSTANT_Float);
-    CPRefBand bc_longref = bc_bands.newCPRefBand("bc_longref", DELTA5, CONSTANT_Long);
-    CPRefBand bc_doubleref = bc_bands.newCPRefBand("bc_doubleref", DELTA5, CONSTANT_Double);
-    CPRefBand bc_stringref = bc_bands.newCPRefBand("bc_stringref", DELTA5, CONSTANT_String);
-    CPRefBand bc_loadablevalueref = bc_bands.newCPRefBand("bc_loadablevalueref", DELTA5, CONSTANT_LoadableValue);
-
-    // nulls produced by bc_classref are taken to mean the current class
-    CPRefBand bc_classref = bc_bands.newCPRefBand("bc_classref", UNSIGNED5, CONSTANT_Class, NULL_IS_OK);   // new, *anew*, c*cast, i*of, ldc
-    CPRefBand bc_fieldref = bc_bands.newCPRefBand("bc_fieldref", DELTA5, CONSTANT_Fieldref);   // get*, put*
-    CPRefBand bc_methodref = bc_bands.newCPRefBand("bc_methodref", CONSTANT_Methodref); // invoke[vs]*
-    CPRefBand bc_imethodref = bc_bands.newCPRefBand("bc_imethodref", DELTA5, CONSTANT_InterfaceMethodref); // invokeinterface
-    CPRefBand bc_indyref = bc_bands.newCPRefBand("bc_indyref", DELTA5, CONSTANT_InvokeDynamic); // invokedynamic
-
-    // _self_linker_op family
-    CPRefBand bc_thisfield = bc_bands.newCPRefBand("bc_thisfield", CONSTANT_None);     // any field within cur. class
-    CPRefBand bc_superfield = bc_bands.newCPRefBand("bc_superfield", CONSTANT_None);   // any field within superclass
-    CPRefBand bc_thismethod = bc_bands.newCPRefBand("bc_thismethod", CONSTANT_None);   // any method within cur. class
-    CPRefBand bc_supermethod = bc_bands.newCPRefBand("bc_supermethod", CONSTANT_None); // any method within superclass
-    // bc_invokeinit family:
-    IntBand   bc_initref = bc_bands.newIntBand("bc_initref");
-    // escapes
-    CPRefBand bc_escref = bc_bands.newCPRefBand("bc_escref", CONSTANT_All);
-    IntBand   bc_escrefsize = bc_bands.newIntBand("bc_escrefsize");
-    IntBand   bc_escsize = bc_bands.newIntBand("bc_escsize");
-    ByteBand  bc_escbyte = bc_bands.newByteBand("bc_escbyte");
-
-    // bands for carrying resource files and file attributes:
-    MultiBand file_bands = all_bands.newMultiBand("(file_bands)", UNSIGNED5);
-    CPRefBand file_name = file_bands.newCPRefBand("file_name", CONSTANT_Utf8);
-    IntBand file_size_hi = file_bands.newIntBand("file_size_hi");
-    IntBand file_size_lo = file_bands.newIntBand("file_size_lo");
-    IntBand file_modtime = file_bands.newIntBand("file_modtime", DELTA5);
-    IntBand file_options = file_bands.newIntBand("file_options");
-    ByteBand file_bits = file_bands.newByteBand("file_bits");
-
-    // End of band definitions!
-
-    /** Given CP indexes, distribute tag-specific indexes to bands. */
-    protected void setBandIndexes() {
-        // Handle prior calls to setBandIndex:
-        for (Object[] need : needPredefIndex) {
-            CPRefBand b     = (CPRefBand) need[0];
-            Byte      which = (Byte)      need[1];
-            b.setIndex(getCPIndex(which.byteValue()));
-        }
-        needPredefIndex = null;  // no more predefs
-
-        if (verbose > 3) {
-            printCDecl(all_bands);
-        }
-    }
-
-    protected void setBandIndex(CPRefBand b, byte which) {
-        Object[] need = { b, Byte.valueOf(which) };
-        if (which == CONSTANT_FieldSpecific) {
-            // I.e., attribute layouts KQ (no null) or KQN (null ok).
-            allKQBands.add(b);
-        } else if (needPredefIndex != null) {
-            needPredefIndex.add(need);
-        } else {
-            // Not in predefinition mode; getCPIndex now works.
-            b.setIndex(getCPIndex(which));
-        }
-    }
-
-    protected void setConstantValueIndex(Field f) {
-        Index ix = null;
-        if (f != null) {
-            byte tag = f.getLiteralTag();
-            ix = getCPIndex(tag);
-            if (verbose > 2)
-                Utils.log.fine("setConstantValueIndex "+f+" "+ConstantPool.tagName(tag)+" => "+ix);
-            assert(ix != null);
-        }
-        // Typically, allKQBands is the singleton of field_ConstantValue_KQ.
-        for (CPRefBand xxx_KQ : allKQBands) {
-            xxx_KQ.setIndex(ix);
-        }
-    }
-
-    // Table of bands which contain metadata.
-    protected MultiBand[] metadataBands = new MultiBand[ATTR_CONTEXT_LIMIT];
-    {
-        metadataBands[ATTR_CONTEXT_CLASS] = class_metadata_bands;
-        metadataBands[ATTR_CONTEXT_FIELD] = field_metadata_bands;
-        metadataBands[ATTR_CONTEXT_METHOD] = method_metadata_bands;
-    }
-    // Table of bands which contains type_metadata (TypeAnnotations)
-    protected MultiBand[] typeMetadataBands = new MultiBand[ATTR_CONTEXT_LIMIT];
-    {
-        typeMetadataBands[ATTR_CONTEXT_CLASS] = class_type_metadata_bands;
-        typeMetadataBands[ATTR_CONTEXT_FIELD] = field_type_metadata_bands;
-        typeMetadataBands[ATTR_CONTEXT_METHOD] = method_type_metadata_bands;
-        typeMetadataBands[ATTR_CONTEXT_CODE]   = code_type_metadata_bands;
-    }
-
-    // Attribute layouts.
-    public static final int ADH_CONTEXT_MASK   = 0x3;  // (ad_hdr & ADH_CONTEXT_MASK)
-    public static final int ADH_BIT_SHIFT      = 0x2;  // (ad_hdr >> ADH_BIT_SHIFT)
-    public static final int ADH_BIT_IS_LSB     = 1;
-    public static final int ATTR_INDEX_OVERFLOW  = -1;
-
-    public int[] attrIndexLimit = new int[ATTR_CONTEXT_LIMIT];
-    // Each index limit is either 32 or 63, depending on AO_HAVE_XXX_FLAGS_HI.
-
-    // Which flag bits are taken over by attributes?
-    protected long[] attrFlagMask = new long[ATTR_CONTEXT_LIMIT];
-    // Which flag bits have been taken over explicitly?
-    protected long[] attrDefSeen = new long[ATTR_CONTEXT_LIMIT];
-
-    // What pseudo-attribute bits are there to watch for?
-    protected int[] attrOverflowMask = new int[ATTR_CONTEXT_LIMIT];
-    protected int attrClassFileVersionMask;
-
-    // Mapping from Attribute.Layout to Band[] (layout element bands).
-    protected Map<Attribute.Layout, Band[]> attrBandTable = new HashMap<>();
-
-    // Well-known attributes:
-    protected final Attribute.Layout attrCodeEmpty;
-    protected final Attribute.Layout attrInnerClassesEmpty;
-    protected final Attribute.Layout attrClassFileVersion;
-    protected final Attribute.Layout attrConstantValue;
-
-    // Mapping from Attribute.Layout to Integer (inverse of attrDefs)
-    Map<Attribute.Layout, Integer> attrIndexTable = new HashMap<>();
-
-    // Mapping from attribute index (<32 are flag bits) to attributes.
-    protected List<List<Attribute.Layout>> attrDefs =
-            new FixedList<>(ATTR_CONTEXT_LIMIT);
-    {
-        for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
-            assert(attrIndexLimit[i] == 0);
-            attrIndexLimit[i] = 32;  // just for the sake of predefs.
-            attrDefs.set(i, new ArrayList<>(Collections.nCopies(
-                    attrIndexLimit[i], (Attribute.Layout)null)));
-
-        }
-
-        // Add predefined attribute definitions:
-        attrInnerClassesEmpty =
-        predefineAttribute(CLASS_ATTR_InnerClasses, ATTR_CONTEXT_CLASS, null,
-                           "InnerClasses", "");
-        assert(attrInnerClassesEmpty == Package.attrInnerClassesEmpty);
-        predefineAttribute(CLASS_ATTR_SourceFile, ATTR_CONTEXT_CLASS,
-                           new Band[] { class_SourceFile_RUN },
-                           "SourceFile", "RUNH");
-        predefineAttribute(CLASS_ATTR_EnclosingMethod, ATTR_CONTEXT_CLASS,
-                           new Band[] {
-                               class_EnclosingMethod_RC,
-                               class_EnclosingMethod_RDN
-                           },
-                           "EnclosingMethod", "RCHRDNH");
-        attrClassFileVersion =
-        predefineAttribute(CLASS_ATTR_ClassFile_version, ATTR_CONTEXT_CLASS,
-                           new Band[] {
-                               class_ClassFile_version_minor_H,
-                               class_ClassFile_version_major_H
-                           },
-                           ".ClassFile.version", "HH");
-        predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_CLASS,
-                           new Band[] { class_Signature_RS },
-                           "Signature", "RSH");
-        predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_CLASS, null,
-                           "Deprecated", "");
-        //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_CLASS, null,
-        //                 "Synthetic", "");
-        predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_CLASS, null,
-                           ".Overflow", "");
-        attrConstantValue =
-        predefineAttribute(FIELD_ATTR_ConstantValue, ATTR_CONTEXT_FIELD,
-                           new Band[] { field_ConstantValue_KQ },
-                           "ConstantValue", "KQH");
-        predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_FIELD,
-                           new Band[] { field_Signature_RS },
-                           "Signature", "RSH");
-        predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_FIELD, null,
-                           "Deprecated", "");
-        //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_FIELD, null,
-        //                 "Synthetic", "");
-        predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_FIELD, null,
-                           ".Overflow", "");
-        attrCodeEmpty =
-        predefineAttribute(METHOD_ATTR_Code, ATTR_CONTEXT_METHOD, null,
-                           "Code", "");
-        predefineAttribute(METHOD_ATTR_Exceptions, ATTR_CONTEXT_METHOD,
-                           new Band[] {
-                               method_Exceptions_N,
-                               method_Exceptions_RC
-                           },
-                           "Exceptions", "NH[RCH]");
-        predefineAttribute(METHOD_ATTR_MethodParameters, ATTR_CONTEXT_METHOD,
-                           new Band[]{
-                                method_MethodParameters_NB,
-                                method_MethodParameters_name_RUN,
-                                method_MethodParameters_flag_FH
-                           },
-                           "MethodParameters", "NB[RUNHFH]");
-        assert(attrCodeEmpty == Package.attrCodeEmpty);
-        predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_METHOD,
-                           new Band[] { method_Signature_RS },
-                           "Signature", "RSH");
-        predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_METHOD, null,
-                           "Deprecated", "");
-        //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_METHOD, null,
-        //                 "Synthetic", "");
-        predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_METHOD, null,
-                           ".Overflow", "");
-
-        for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) {
-            MultiBand xxx_metadata_bands = metadataBands[ctype];
-            if (ctype != ATTR_CONTEXT_CODE) {
-                // These arguments cause the bands to be built
-                // automatically for this complicated layout:
-                predefineAttribute(X_ATTR_RuntimeVisibleAnnotations,
-                                   ATTR_CONTEXT_NAME[ctype]+"_RVA_",
-                                   xxx_metadata_bands,
-                                   Attribute.lookup(null, ctype,
-                                                    "RuntimeVisibleAnnotations"));
-                predefineAttribute(X_ATTR_RuntimeInvisibleAnnotations,
-                                   ATTR_CONTEXT_NAME[ctype]+"_RIA_",
-                                   xxx_metadata_bands,
-                                   Attribute.lookup(null, ctype,
-                                                    "RuntimeInvisibleAnnotations"));
-
-                if (ctype == ATTR_CONTEXT_METHOD) {
-                    predefineAttribute(METHOD_ATTR_RuntimeVisibleParameterAnnotations,
-                                       "method_RVPA_", xxx_metadata_bands,
-                                       Attribute.lookup(null, ctype,
-                                       "RuntimeVisibleParameterAnnotations"));
-                    predefineAttribute(METHOD_ATTR_RuntimeInvisibleParameterAnnotations,
-                                       "method_RIPA_", xxx_metadata_bands,
-                                       Attribute.lookup(null, ctype,
-                                       "RuntimeInvisibleParameterAnnotations"));
-                    predefineAttribute(METHOD_ATTR_AnnotationDefault,
-                                       "method_AD_", xxx_metadata_bands,
-                                       Attribute.lookup(null, ctype,
-                                       "AnnotationDefault"));
-                }
-            }
-            // All contexts have these
-            MultiBand xxx_type_metadata_bands = typeMetadataBands[ctype];
-            predefineAttribute(X_ATTR_RuntimeVisibleTypeAnnotations,
-                    ATTR_CONTEXT_NAME[ctype] + "_RVTA_",
-                    xxx_type_metadata_bands,
-                    Attribute.lookup(null, ctype,
-                    "RuntimeVisibleTypeAnnotations"));
-            predefineAttribute(X_ATTR_RuntimeInvisibleTypeAnnotations,
-                    ATTR_CONTEXT_NAME[ctype] + "_RITA_",
-                    xxx_type_metadata_bands,
-                    Attribute.lookup(null, ctype,
-                    "RuntimeInvisibleTypeAnnotations"));
-        }
-
-
-        Attribute.Layout stackMapDef = Attribute.lookup(null, ATTR_CONTEXT_CODE, "StackMapTable").layout();
-        predefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE,
-                           stackmap_bands.toArray(),
-                           stackMapDef.name(), stackMapDef.layout());
-
-        predefineAttribute(CODE_ATTR_LineNumberTable, ATTR_CONTEXT_CODE,
-                           new Band[] {
-                               code_LineNumberTable_N,
-                               code_LineNumberTable_bci_P,
-                               code_LineNumberTable_line
-                           },
-                           "LineNumberTable", "NH[PHH]");
-        predefineAttribute(CODE_ATTR_LocalVariableTable, ATTR_CONTEXT_CODE,
-                           new Band[] {
-                               code_LocalVariableTable_N,
-                               code_LocalVariableTable_bci_P,
-                               code_LocalVariableTable_span_O,
-                               code_LocalVariableTable_name_RU,
-                               code_LocalVariableTable_type_RS,
-                               code_LocalVariableTable_slot
-                           },
-                           "LocalVariableTable", "NH[PHOHRUHRSHH]");
-        predefineAttribute(CODE_ATTR_LocalVariableTypeTable, ATTR_CONTEXT_CODE,
-                           new Band[] {
-                               code_LocalVariableTypeTable_N,
-                               code_LocalVariableTypeTable_bci_P,
-                               code_LocalVariableTypeTable_span_O,
-                               code_LocalVariableTypeTable_name_RU,
-                               code_LocalVariableTypeTable_type_RS,
-                               code_LocalVariableTypeTable_slot
-                           },
-                           "LocalVariableTypeTable", "NH[PHOHRUHRSHH]");
-        predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_CODE, null,
-                           ".Overflow", "");
-
-        // Clear the record of having seen these definitions,
-        // so they may be redefined without error.
-        for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
-            attrDefSeen[i] = 0;
-        }
-
-        // Set up the special masks:
-        for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
-            attrOverflowMask[i] = (1<<X_ATTR_OVERFLOW);
-            attrIndexLimit[i] = 0;  // will make a final decision later
-        }
-        attrClassFileVersionMask = (1<<CLASS_ATTR_ClassFile_version);
-    }
-
-    private void adjustToClassVersion() throws IOException {
-        if (getHighestClassVersion().lessThan(JAVA6_MAX_CLASS_VERSION)) {
-            if (verbose > 0)  Utils.log.fine("Legacy package version");
-            // Revoke definition of pre-1.6 attribute type.
-            undefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE);
-        }
-    }
-
-    protected void initAttrIndexLimit() {
-        for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
-            assert(attrIndexLimit[i] == 0);  // decide on it now!
-            attrIndexLimit[i] = (haveFlagsHi(i)? 63: 32);
-            List<Attribute.Layout> defList = attrDefs.get(i);
-            assert(defList.size() == 32);  // all predef indexes are <32
-            int addMore = attrIndexLimit[i] - defList.size();
-            defList.addAll(Collections.nCopies(addMore, (Attribute.Layout) null));
-        }
-    }
-
-    protected boolean haveFlagsHi(int ctype) {
-        int mask = 1<<(LG_AO_HAVE_XXX_FLAGS_HI+ctype);
-        switch (ctype) {
-        case ATTR_CONTEXT_CLASS:
-            assert(mask == AO_HAVE_CLASS_FLAGS_HI); break;
-        case ATTR_CONTEXT_FIELD:
-            assert(mask == AO_HAVE_FIELD_FLAGS_HI); break;
-        case ATTR_CONTEXT_METHOD:
-            assert(mask == AO_HAVE_METHOD_FLAGS_HI); break;
-        case ATTR_CONTEXT_CODE:
-            assert(mask == AO_HAVE_CODE_FLAGS_HI); break;
-        default:
-            assert(false);
-        }
-        return testBit(archiveOptions, mask);
-    }
-
-    protected List<Attribute.Layout> getPredefinedAttrs(int ctype) {
-        assert(attrIndexLimit[ctype] != 0);
-        List<Attribute.Layout> res = new ArrayList<>(attrIndexLimit[ctype]);
-        // Remove nulls and non-predefs.
-        for (int ai = 0; ai < attrIndexLimit[ctype]; ai++) {
-            if (testBit(attrDefSeen[ctype], 1L<<ai))  continue;
-            Attribute.Layout def = attrDefs.get(ctype).get(ai);
-            if (def == null)  continue;  // unused flag bit
-            assert(isPredefinedAttr(ctype, ai));
-            res.add(def);
-        }
-        return res;
-    }
-
-    protected boolean isPredefinedAttr(int ctype, int ai) {
-        assert(attrIndexLimit[ctype] != 0);
-        // Overflow attrs are never predefined.
-        if (ai >= attrIndexLimit[ctype])          return false;
-        // If the bit is set, it was explicitly def'd.
-        if (testBit(attrDefSeen[ctype], 1L<<ai))  return false;
-        return (attrDefs.get(ctype).get(ai) != null);
-    }
-
-    protected void adjustSpecialAttrMasks() {
-        // Clear special masks if new definitions have been seen for them.
-        attrClassFileVersionMask &= ~ attrDefSeen[ATTR_CONTEXT_CLASS];
-        // It is possible to clear the overflow mask (bit 16).
-        for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
-            attrOverflowMask[i] &= ~ attrDefSeen[i];
-        }
-    }
-
-    protected Attribute makeClassFileVersionAttr(Package.Version ver) {
-        return attrClassFileVersion.addContent(ver.asBytes());
-    }
-
-    protected Package.Version parseClassFileVersionAttr(Attribute attr) {
-        assert(attr.layout() == attrClassFileVersion);
-        assert(attr.size() == 4);
-        return Package.Version.of(attr.bytes());
-    }
-
-    private boolean assertBandOKForElems(Band[] ab, Attribute.Layout.Element[] elems) {
-        for (int i = 0; i < elems.length; i++) {
-            assert(assertBandOKForElem(ab, elems[i]));
-        }
-        return true;
-    }
-    private boolean assertBandOKForElem(Band[] ab, Attribute.Layout.Element e) {
-        Band b = null;
-        if (e.bandIndex != Attribute.NO_BAND_INDEX)
-            b = ab[e.bandIndex];
-        Coding rc = UNSIGNED5;
-        boolean wantIntBand = true;
-        switch (e.kind) {
-        case Attribute.EK_INT:
-            if (e.flagTest(Attribute.EF_SIGN)) {
-                rc = SIGNED5;
-            } else if (e.len == 1) {
-                rc = BYTE1;
-            }
-            break;
-        case Attribute.EK_BCI:
-            if (!e.flagTest(Attribute.EF_DELTA)) {
-                rc = BCI5;
-            } else {
-                rc = BRANCH5;
-            }
-            break;
-        case Attribute.EK_BCO:
-            rc = BRANCH5;
-            break;
-        case Attribute.EK_FLAG:
-            if (e.len == 1)  rc = BYTE1;
-            break;
-        case Attribute.EK_REPL:
-            if (e.len == 1)  rc = BYTE1;
-            assertBandOKForElems(ab, e.body);
-            break;
-        case Attribute.EK_UN:
-            if (e.flagTest(Attribute.EF_SIGN)) {
-                rc = SIGNED5;
-            } else if (e.len == 1) {
-                rc = BYTE1;
-            }
-            assertBandOKForElems(ab, e.body);
-            break;
-        case Attribute.EK_CASE:
-            assert(b == null);
-            assertBandOKForElems(ab, e.body);
-            return true;  // no direct band
-        case Attribute.EK_CALL:
-            assert(b == null);
-            return true;  // no direct band
-        case Attribute.EK_CBLE:
-            assert(b == null);
-            assertBandOKForElems(ab, e.body);
-            return true;  // no direct band
-        case Attribute.EK_REF:
-            wantIntBand = false;
-            assert(b instanceof CPRefBand);
-            assert(((CPRefBand)b).nullOK == e.flagTest(Attribute.EF_NULL));
-            break;
-        default: assert(false);
-        }
-        assert(b.regularCoding == rc)
-            : (e+" // "+b);
-        if (wantIntBand)
-            assert(b instanceof IntBand);
-        return true;
-    }
-
-    private
-    Attribute.Layout predefineAttribute(int index, int ctype, Band[] ab,
-                                        String name, String layout) {
-        // Use Attribute.find to get uniquification of layouts.
-        Attribute.Layout def = Attribute.find(ctype, name, layout).layout();
-        //def.predef = true;
-        if (index >= 0) {
-            setAttributeLayoutIndex(def, index);
-        }
-        if (ab == null) {
-            ab = new Band[0];
-        }
-        assert(attrBandTable.get(def) == null);  // no redef
-        attrBandTable.put(def, ab);
-        assert(def.bandCount == ab.length)
-            : (def+" // "+Arrays.asList(ab));
-        // Let's make sure the band types match:
-        assert(assertBandOKForElems(ab, def.elems));
-        return def;
-    }
-
-    // This version takes bandPrefix/addHere instead of prebuilt Band[] ab.
-    private
-    Attribute.Layout predefineAttribute(int index,
-                                        String bandPrefix, MultiBand addHere,
-                                        Attribute attr) {
-        //Attribute.Layout def = Attribute.find(ctype, name, layout).layout();
-        Attribute.Layout def = attr.layout();
-        int ctype = def.ctype();
-        return predefineAttribute(index, ctype,
-                                  makeNewAttributeBands(bandPrefix, def, addHere),
-                                  def.name(), def.layout());
-    }
-
-    private
-    void undefineAttribute(int index, int ctype) {
-        if (verbose > 1) {
-            System.out.println("Removing predefined "+ATTR_CONTEXT_NAME[ctype]+
-                               " attribute on bit "+index);
-        }
-        List<Attribute.Layout> defList = attrDefs.get(ctype);
-        Attribute.Layout def = defList.get(index);
-        assert(def != null);
-        defList.set(index, null);
-        attrIndexTable.put(def, null);
-        // Clear the def bit.  (For predefs, it's already clear.)
-        assert(index < 64);
-        attrDefSeen[ctype]  &= ~(1L<<index);
-        attrFlagMask[ctype] &= ~(1L<<index);
-        Band[] ab = attrBandTable.get(def);
-        for (int j = 0; j < ab.length; j++) {
-            ab[j].doneWithUnusedBand();
-        }
-    }
-
-    // Bands which contain non-predefined attrs.
-    protected MultiBand[] attrBands = new MultiBand[ATTR_CONTEXT_LIMIT];
-    {
-        attrBands[ATTR_CONTEXT_CLASS] = class_attr_bands;
-        attrBands[ATTR_CONTEXT_FIELD] = field_attr_bands;
-        attrBands[ATTR_CONTEXT_METHOD] = method_attr_bands;
-        attrBands[ATTR_CONTEXT_CODE] = code_attr_bands;
-    }
-
-    // Create bands for all non-predefined attrs.
-    void makeNewAttributeBands() {
-        // Retract special flag bit bindings, if they were taken over.
-        adjustSpecialAttrMasks();
-
-        for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) {
-            String cname = ATTR_CONTEXT_NAME[ctype];
-            MultiBand xxx_attr_bands = attrBands[ctype];
-            long defSeen = attrDefSeen[ctype];
-            // Note: attrDefSeen is always a subset of attrFlagMask.
-            assert((defSeen & ~attrFlagMask[ctype]) == 0);
-            for (int i = 0; i < attrDefs.get(ctype).size(); i++) {
-                Attribute.Layout def = attrDefs.get(ctype).get(i);
-                if (def == null)  continue;  // unused flag bit
-                if (def.bandCount == 0)  continue;  // empty attr
-                if (i < attrIndexLimit[ctype] && !testBit(defSeen, 1L<<i)) {
-                    // There are already predefined bands here.
-                    assert(attrBandTable.get(def) != null);
-                    continue;
-                }
-                int base = xxx_attr_bands.size();
-                String pfx = cname+"_"+def.name()+"_";  // debug only
-                if (verbose > 1)
-                    Utils.log.fine("Making new bands for "+def);
-                Band[] newAB  = makeNewAttributeBands(pfx, def,
-                                                      xxx_attr_bands);
-                assert(newAB.length == def.bandCount);
-                Band[] prevAB = attrBandTable.put(def, newAB);
-                if (prevAB != null) {
-                    // We won't be using these predefined bands.
-                    for (int j = 0; j < prevAB.length; j++) {
-                        prevAB[j].doneWithUnusedBand();
-                    }
-                }
-            }
-        }
-        //System.out.println(prevForAssertMap);
-    }
-    private
-    Band[] makeNewAttributeBands(String pfx, Attribute.Layout def,
-                                 MultiBand addHere) {
-        int base = addHere.size();
-        makeNewAttributeBands(pfx, def.elems, addHere);
-        int nb = addHere.size() - base;
-        Band[] newAB = new Band[nb];
-        for (int i = 0; i < nb; i++) {
-            newAB[i] = addHere.get(base+i);
-        }
-        return newAB;
-    }
-    // Recursive helper, operates on a "body" or other sequence of elems:
-    private
-    void makeNewAttributeBands(String pfx, Attribute.Layout.Element[] elems,
-                               MultiBand ab) {
-        for (int i = 0; i < elems.length; i++) {
-            Attribute.Layout.Element e = elems[i];
-            String name = pfx+ab.size()+"_"+e.layout;
-            {
-                int tem;
-                if ((tem = name.indexOf('[')) > 0)
-                    name = name.substring(0, tem);
-                if ((tem = name.indexOf('(')) > 0)
-                    name = name.substring(0, tem);
-                if (name.endsWith("H"))
-                    name = name.substring(0, name.length()-1);
-            }
-            Band nb;
-            switch (e.kind) {
-            case Attribute.EK_INT:
-                nb = newElemBand(e, name, ab);
-                break;
-            case Attribute.EK_BCI:
-                if (!e.flagTest(Attribute.EF_DELTA)) {
-                    // PH:  transmit R(bci), store bci
-                    nb = ab.newIntBand(name, BCI5);
-                } else {
-                    // POH:  transmit D(R(bci)), store bci
-                    nb = ab.newIntBand(name, BRANCH5);
-                }
-                // Note:  No case for BYTE1 here.
-                break;
-            case Attribute.EK_BCO:
-                // OH:  transmit D(R(bci)), store D(bci)
-                nb = ab.newIntBand(name, BRANCH5);
-                // Note:  No case for BYTE1 here.
-                break;
-            case Attribute.EK_FLAG:
-                assert(!e.flagTest(Attribute.EF_SIGN));
-                nb = newElemBand(e, name, ab);
-                break;
-            case Attribute.EK_REPL:
-                assert(!e.flagTest(Attribute.EF_SIGN));
-                nb = newElemBand(e, name, ab);
-                makeNewAttributeBands(pfx, e.body, ab);
-                break;
-            case Attribute.EK_UN:
-                nb = newElemBand(e, name, ab);
-                makeNewAttributeBands(pfx, e.body, ab);
-                break;
-            case Attribute.EK_CASE:
-                if (!e.flagTest(Attribute.EF_BACK)) {
-                    // If it's not a duplicate body, make the bands.
-                    makeNewAttributeBands(pfx, e.body, ab);
-                }
-                continue;  // no new band to make
-            case Attribute.EK_REF:
-                byte    refKind = e.refKind;
-                boolean nullOK  = e.flagTest(Attribute.EF_NULL);
-                nb = ab.newCPRefBand(name, UNSIGNED5, refKind, nullOK);
-                // Note:  No case for BYTE1 here.
-                break;
-            case Attribute.EK_CALL:
-                continue;  // no new band to make
-            case Attribute.EK_CBLE:
-                makeNewAttributeBands(pfx, e.body, ab);
-                continue;  // no new band to make
-            default: assert(false); continue;
-            }
-            if (verbose > 1) {
-                Utils.log.fine("New attribute band "+nb);
-            }
-        }
-    }
-    private
-    Band newElemBand(Attribute.Layout.Element e, String name, MultiBand ab) {
-        if (e.flagTest(Attribute.EF_SIGN)) {
-            return ab.newIntBand(name, SIGNED5);
-        } else if (e.len == 1) {
-            return ab.newIntBand(name, BYTE1);  // Not ByteBand, please.
-        } else {
-            return ab.newIntBand(name, UNSIGNED5);
-        }
-    }
-
-    protected int setAttributeLayoutIndex(Attribute.Layout def, int index) {
-        int ctype = def.ctype;
-        assert(ATTR_INDEX_OVERFLOW <= index && index < attrIndexLimit[ctype]);
-        List<Attribute.Layout> defList = attrDefs.get(ctype);
-        if (index == ATTR_INDEX_OVERFLOW) {
-            // Overflow attribute.
-            index = defList.size();
-            defList.add(def);
-            if (verbose > 0)
-                Utils.log.info("Adding new attribute at "+def +": "+index);
-            attrIndexTable.put(def, index);
-            return index;
-        }
-
-        // Detect redefinitions:
-        if (testBit(attrDefSeen[ctype], 1L<<index)) {
-            throw new RuntimeException("Multiple explicit definition at "+index+": "+def);
-        }
-        attrDefSeen[ctype] |= (1L<<index);
-
-        // Adding a new fixed attribute.
-        assert(0 <= index && index < attrIndexLimit[ctype]);
-        if (verbose > (attrClassFileVersionMask == 0? 2:0))
-            Utils.log.fine("Fixing new attribute at "+index
-                               +": "+def
-                               +(defList.get(index) == null? "":
-                                 "; replacing "+defList.get(index)));
-        attrFlagMask[ctype] |= (1L<<index);
-        // Remove index binding of any previous fixed attr.
-        attrIndexTable.put(defList.get(index), null);
-        defList.set(index, def);
-        attrIndexTable.put(def, index);
-        return index;
-    }
-
-    // encodings found in the code_headers band
-    private static final int[][] shortCodeLimits = {
-        { 12, 12 }, // s<12, l<12, e=0 [1..144]
-        {  8,  8 }, //  s<8,  l<8, e=1 [145..208]
-        {  7,  7 }, //  s<7,  l<7, e=2 [209..256]
-    };
-    public final int shortCodeHeader_h_limit = shortCodeLimits.length;
-
-    // return 0 if it won't encode, else a number in [1..255]
-    static int shortCodeHeader(Code code) {
-        int s = code.max_stack;
-        int l0 = code.max_locals;
-        int h = code.handler_class.length;
-        if (h >= shortCodeLimits.length)  return LONG_CODE_HEADER;
-        int siglen = code.getMethod().getArgumentSize();
-        assert(l0 >= siglen);  // enough locals for signature!
-        if (l0 < siglen)  return LONG_CODE_HEADER;
-        int l1 = l0 - siglen;  // do not count locals required by the signature
-        int lims = shortCodeLimits[h][0];
-        int liml = shortCodeLimits[h][1];
-        if (s >= lims || l1 >= liml)  return LONG_CODE_HEADER;
-        int sc = shortCodeHeader_h_base(h);
-        sc += s + lims*l1;
-        if (sc > 255)  return LONG_CODE_HEADER;
-        assert(shortCodeHeader_max_stack(sc) == s);
-        assert(shortCodeHeader_max_na_locals(sc) == l1);
-        assert(shortCodeHeader_handler_count(sc) == h);
-        return sc;
-    }
-
-    static final int LONG_CODE_HEADER = 0;
-    static int shortCodeHeader_handler_count(int sc) {
-        assert(sc > 0 && sc <= 255);
-        for (int h = 0; ; h++) {
-            if (sc < shortCodeHeader_h_base(h+1))
-                return h;
-        }
-    }
-    static int shortCodeHeader_max_stack(int sc) {
-        int h = shortCodeHeader_handler_count(sc);
-        int lims = shortCodeLimits[h][0];
-        return (sc - shortCodeHeader_h_base(h)) % lims;
-    }
-    static int shortCodeHeader_max_na_locals(int sc) {
-        int h = shortCodeHeader_handler_count(sc);
-        int lims = shortCodeLimits[h][0];
-        return (sc - shortCodeHeader_h_base(h)) / lims;
-    }
-
-    private static int shortCodeHeader_h_base(int h) {
-        assert(h <= shortCodeLimits.length);
-        int sc = 1;
-        for (int h0 = 0; h0 < h; h0++) {
-            int lims = shortCodeLimits[h0][0];
-            int liml = shortCodeLimits[h0][1];
-            sc += lims * liml;
-        }
-        return sc;
-    }
-
-    // utilities for accessing the bc_label band:
-    protected void putLabel(IntBand bc_label, Code c, int pc, int targetPC) {
-        bc_label.putInt(c.encodeBCI(targetPC) - c.encodeBCI(pc));
-    }
-    protected int getLabel(IntBand bc_label, Code c, int pc) {
-        return c.decodeBCI(bc_label.getInt() + c.encodeBCI(pc));
-    }
-
-    protected CPRefBand getCPRefOpBand(int bc) {
-        switch (Instruction.getCPRefOpTag(bc)) {
-        case CONSTANT_Class:
-            return bc_classref;
-        case CONSTANT_Fieldref:
-            return bc_fieldref;
-        case CONSTANT_Methodref:
-            return bc_methodref;
-        case CONSTANT_InterfaceMethodref:
-            return bc_imethodref;
-        case CONSTANT_InvokeDynamic:
-            return bc_indyref;
-        case CONSTANT_LoadableValue:
-            switch (bc) {
-            case _ildc: case _ildc_w:
-                return bc_intref;
-            case _fldc: case _fldc_w:
-                return bc_floatref;
-            case _lldc2_w:
-                return bc_longref;
-            case _dldc2_w:
-                return bc_doubleref;
-            case _sldc: case _sldc_w:
-                return bc_stringref;
-            case _cldc: case _cldc_w:
-                return bc_classref;
-            case _qldc: case _qldc_w:
-                return bc_loadablevalueref;
-            }
-            break;
-        }
-        assert(false);
-        return null;
-    }
-
-    protected CPRefBand selfOpRefBand(int self_bc) {
-        assert(Instruction.isSelfLinkerOp(self_bc));
-        int idx = (self_bc - _self_linker_op);
-        boolean isSuper = (idx >= _self_linker_super_flag);
-        if (isSuper)  idx -= _self_linker_super_flag;
-        boolean isAload = (idx >= _self_linker_aload_flag);
-        if (isAload)  idx -= _self_linker_aload_flag;
-        int origBC = _first_linker_op + idx;
-        boolean isField = Instruction.isFieldOp(origBC);
-        if (!isSuper)
-            return isField? bc_thisfield: bc_thismethod;
-        else
-            return isField? bc_superfield: bc_supermethod;
-    }
-
-    ////////////////////////////////////////////////////////////////////
-
-    static int nextSeqForDebug;
-    static File dumpDir = null;
-    static OutputStream getDumpStream(Band b, String ext) throws IOException {
-        return getDumpStream(b.name, b.seqForDebug, ext, b);
-    }
-    static OutputStream getDumpStream(Index ix, String ext) throws IOException {
-        if (ix.size() == 0)  return new ByteArrayOutputStream();
-        int seq = ConstantPool.TAG_ORDER[ix.cpMap[0].tag];
-        return getDumpStream(ix.debugName, seq, ext, ix);
-    }
-    static OutputStream getDumpStream(String name, int seq, String ext, Object b) throws IOException {
-        if (dumpDir == null) {
-            dumpDir = File.createTempFile("BD_", "", new File("."));
-            dumpDir.delete();
-            if (dumpDir.mkdir())
-                Utils.log.info("Dumping bands to "+dumpDir);
-        }
-        name = name.replace('(', ' ').replace(')', ' ');
-        name = name.replace('/', ' ');
-        name = name.replace('*', ' ');
-        name = name.trim().replace(' ','_');
-        name = ((10000+seq) + "_" + name).substring(1);
-        File dumpFile = new File(dumpDir, name+ext);
-        Utils.log.info("Dumping "+b+" to "+dumpFile);
-        return new BufferedOutputStream(new FileOutputStream(dumpFile));
-    }
-
-    // DEBUG ONLY:  Validate me at each length change.
-    static boolean assertCanChangeLength(Band b) {
-        switch (b.phase) {
-        case COLLECT_PHASE:
-        case READ_PHASE:
-            return true;
-        }
-        return false;
-    }
-
-    // DEBUG ONLY:  Validate a phase.
-    static boolean assertPhase(Band b, int phaseExpected) {
-        if (b.phase() != phaseExpected) {
-            Utils.log.warning("phase expected "+phaseExpected+" was "+b.phase()+" in "+b);
-            return false;
-        }
-        return true;
-    }
-
-
-    // DEBUG ONLY:  Tells whether verbosity is turned on.
-    static int verbose() {
-        return Utils.currentPropMap().getInteger(Utils.DEBUG_VERBOSE);
-    }
-
-
-    // DEBUG ONLY:  Validate me at each phase change.
-    static boolean assertPhaseChangeOK(Band b, int p0, int p1) {
-        switch (p0*10+p1) {
-        /// Writing phases:
-        case NO_PHASE*10+COLLECT_PHASE:
-            // Ready to collect data from the input classes.
-            assert(!b.isReader());
-            assert(b.capacity() >= 0);
-            assert(b.length() == 0);
-            return true;
-        case COLLECT_PHASE*10+FROZEN_PHASE:
-        case FROZEN_PHASE*10+FROZEN_PHASE:
-            assert(b.length() == 0);
-            return true;
-        case COLLECT_PHASE*10+WRITE_PHASE:
-        case FROZEN_PHASE*10+WRITE_PHASE:
-            // Data is all collected.  Ready to write bytes to disk.
-            return true;
-        case WRITE_PHASE*10+DONE_PHASE:
-            // Done writing to disk.  Ready to reset, in principle.
-            return true;
-
-        /// Reading phases:
-        case NO_PHASE*10+EXPECT_PHASE:
-            assert(b.isReader());
-            assert(b.capacity() < 0);
-            return true;
-        case EXPECT_PHASE*10+READ_PHASE:
-            // Ready to read values from disk.
-            assert(Math.max(0,b.capacity()) >= b.valuesExpected());
-            assert(b.length() <= 0);
-            return true;
-        case READ_PHASE*10+DISBURSE_PHASE:
-            // Ready to disburse values.
-            assert(b.valuesRemainingForDebug() == b.length());
-            return true;
-        case DISBURSE_PHASE*10+DONE_PHASE:
-            // Done disbursing values.  Ready to reset, in principle.
-            assert(assertDoneDisbursing(b));
-            return true;
-        }
-        if (p0 == p1)
-            Utils.log.warning("Already in phase "+p0);
-        else
-            Utils.log.warning("Unexpected phase "+p0+" -> "+p1);
-        return false;
-    }
-
-    private static boolean assertDoneDisbursing(Band b) {
-        if (b.phase != DISBURSE_PHASE) {
-            Utils.log.warning("assertDoneDisbursing: still in phase "+b.phase+": "+b);
-            if (verbose() <= 1)  return false;  // fail now
-        }
-        int left = b.valuesRemainingForDebug();
-        if (left > 0) {
-            Utils.log.warning("assertDoneDisbursing: "+left+" values left in "+b);
-            if (verbose() <= 1)  return false;  // fail now
-        }
-        if (b instanceof MultiBand) {
-            MultiBand mb = (MultiBand) b;
-            for (int i = 0; i < mb.bandCount; i++) {
-                Band sub = mb.bands[i];
-                if (sub.phase != DONE_PHASE) {
-                    Utils.log.warning("assertDoneDisbursing: sub-band still in phase "+sub.phase+": "+sub);
-                    if (verbose() <= 1)  return false;  // fail now
-                }
-            }
-        }
-        return true;
-    }
-
-    private static void printCDecl(Band b) {
-        if (b instanceof MultiBand) {
-            MultiBand mb = (MultiBand) b;
-            for (int i = 0; i < mb.bandCount; i++) {
-                printCDecl(mb.bands[i]);
-            }
-            return;
-        }
-        String ixS = "NULL";
-        if (b instanceof CPRefBand) {
-            Index ix = ((CPRefBand)b).index;
-            if (ix != null)  ixS = "INDEX("+ix.debugName+")";
-        }
-        Coding[] knownc = { BYTE1, CHAR3, BCI5, BRANCH5, UNSIGNED5,
-                            UDELTA5, SIGNED5, DELTA5, MDELTA5 };
-        String[] knowns = { "BYTE1", "CHAR3", "BCI5", "BRANCH5", "UNSIGNED5",
-                            "UDELTA5", "SIGNED5", "DELTA5", "MDELTA5" };
-        Coding rc = b.regularCoding;
-        int rci = Arrays.asList(knownc).indexOf(rc);
-        String cstr;
-        if (rci >= 0)
-            cstr = knowns[rci];
-        else
-            cstr = "CODING"+rc.keyString();
-        System.out.println("  BAND_INIT(\""+b.name()+"\""
-                           +", "+cstr+", "+ixS+"),");
-    }
-
-    private Map<Band, Band> prevForAssertMap;
-
-    // DEBUG ONLY:  Record something about the band order.
-    boolean notePrevForAssert(Band b, Band p) {
-        if (prevForAssertMap == null)
-            prevForAssertMap = new HashMap<>();
-        prevForAssertMap.put(b, p);
-        return true;
-    }
-
-    // DEBUG ONLY:  Validate next input band, ensure bands are read in sequence
-    private boolean assertReadyToReadFrom(Band b, InputStream in) throws IOException {
-        Band p = prevForAssertMap.get(b);
-        // Any previous band must be done reading before this one starts.
-        if (p != null && phaseCmp(p.phase(), DISBURSE_PHASE) < 0) {
-            Utils.log.warning("Previous band not done reading.");
-            Utils.log.info("    Previous band: "+p);
-            Utils.log.info("        Next band: "+b);
-            assert(verbose > 0);  // die unless verbose is true
-        }
-        String name = b.name;
-        if (optDebugBands && !name.startsWith("(")) {
-            assert(bandSequenceList != null);
-            // Verify synchronization between reader & writer:
-            String inName = bandSequenceList.removeFirst();
-            // System.out.println("Reading: " + name);
-            if (!inName.equals(name)) {
-                Utils.log.warning("Expected " + name + " but read: " + inName);
-                return false;
-            }
-            Utils.log.info("Read band in sequence: " + name);
-        }
-        return true;
-    }
-
-    // DEBUG ONLY:  Make sure a bunch of cprefs are correct.
-    private boolean assertValidCPRefs(CPRefBand b) {
-        if (b.index == null)  return true;
-        int limit = b.index.size()+1;
-        for (int i = 0; i < b.length(); i++) {
-            int v = b.valueAtForDebug(i);
-            if (v < 0 || v >= limit) {
-                Utils.log.warning("CP ref out of range "+
-                                   "["+i+"] = "+v+" in "+b);
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /*
-     * DEBUG ONLY:  write the bands to a list and read back the list in order,
-     * this works perfectly if we use the java packer and unpacker, typically
-     * this will work with --repack or if they are in the same jvm instance.
-     */
-    static LinkedList<String> bandSequenceList = null;
-    private boolean assertReadyToWriteTo(Band b, OutputStream out) throws IOException {
-        Band p = prevForAssertMap.get(b);
-        // Any previous band must be done writing before this one starts.
-        if (p != null && phaseCmp(p.phase(), DONE_PHASE) < 0) {
-            Utils.log.warning("Previous band not done writing.");
-            Utils.log.info("    Previous band: "+p);
-            Utils.log.info("        Next band: "+b);
-            assert(verbose > 0);  // die unless verbose is true
-        }
-        String name = b.name;
-        if (optDebugBands && !name.startsWith("(")) {
-            if (bandSequenceList == null)
-                bandSequenceList = new LinkedList<>();
-            // Verify synchronization between reader & writer:
-            bandSequenceList.add(name);
-            // System.out.println("Writing: " + b);
-        }
-        return true;
-    }
-
-    protected static boolean testBit(int flags, int bitMask) {
-        return (flags & bitMask) != 0;
-    }
-    protected static int setBit(int flags, int bitMask, boolean z) {
-        return z ? (flags | bitMask) : (flags &~ bitMask);
-    }
-    protected static boolean testBit(long flags, long bitMask) {
-        return (flags & bitMask) != 0;
-    }
-    protected static long setBit(long flags, long bitMask, boolean z) {
-        return z ? (flags | bitMask) : (flags &~ bitMask);
-    }
-
-
-    static void printArrayTo(PrintStream ps, int[] values, int start, int end) {
-        int len = end-start;
-        for (int i = 0; i < len; i++) {
-            if (i % 10 == 0)
-                ps.println();
-            else
-                ps.print(" ");
-            ps.print(values[start+i]);
-        }
-        ps.println();
-    }
-
-    static void printArrayTo(PrintStream ps, Entry[] cpMap, int start, int end) {
-        printArrayTo(ps, cpMap, start, end, false);
-    }
-    static void printArrayTo(PrintStream ps, Entry[] cpMap, int start, int end, boolean showTags) {
-        StringBuffer buf = new StringBuffer();
-        int len = end-start;
-        for (int i = 0; i < len; i++) {
-            Entry e = cpMap[start+i];
-            ps.print(start+i); ps.print("=");
-            if (showTags) { ps.print(e.tag); ps.print(":"); }
-            String s = e.stringValue();
-            buf.setLength(0);
-            for (int j = 0; j < s.length(); j++) {
-                char ch = s.charAt(j);
-                if (!(ch < ' ' || ch > '~' || ch == '\\')) {
-                    buf.append(ch);
-                } else if (ch == '\\') {
-                    buf.append("\\\\");
-                } else if (ch == '\n') {
-                    buf.append("\\n");
-                } else if (ch == '\t') {
-                    buf.append("\\t");
-                } else if (ch == '\r') {
-                    buf.append("\\r");
-                } else {
-                    String str = "000"+Integer.toHexString(ch);
-                    buf.append("\\u").append(str.substring(str.length()-4));
-                }
-            }
-            ps.println(buf);
-        }
-    }
-
-
-    // Utilities for reallocating:
-    protected static Object[] realloc(Object[] a, int len) {
-        java.lang.Class<?> elt = a.getClass().getComponentType();
-        Object[] na = (Object[]) java.lang.reflect.Array.newInstance(elt, len);
-        System.arraycopy(a, 0, na, 0, Math.min(a.length, len));
-        return na;
-    }
-    protected static Object[] realloc(Object[] a) {
-        return realloc(a, Math.max(10, a.length*2));
-    }
-
-    protected static int[] realloc(int[] a, int len) {
-        if (len == 0)  return noInts;
-        if (a == null)  return new int[len];
-        int[] na = new int[len];
-        System.arraycopy(a, 0, na, 0, Math.min(a.length, len));
-        return na;
-    }
-    protected static int[] realloc(int[] a) {
-        return realloc(a, Math.max(10, a.length*2));
-    }
-
-    protected static byte[] realloc(byte[] a, int len) {
-        if (len == 0)  return noBytes;
-        if (a == null)  return new byte[len];
-        byte[] na = new byte[len];
-        System.arraycopy(a, 0, na, 0, Math.min(a.length, len));
-        return na;
-    }
-    protected static byte[] realloc(byte[] a) {
-        return realloc(a, Math.max(10, a.length*2));
-    }
-}
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/ClassReader.java	Mon Dec 09 15:28:46 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,619 +0,0 @@
-/*
- * Copyright (c) 2001, 2019, 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.Entry;
-import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry;
-import com.sun.java.util.jar.pack.ConstantPool.MemberEntry;
-import com.sun.java.util.jar.pack.ConstantPool.MethodHandleEntry;
-import com.sun.java.util.jar.pack.ConstantPool.BootstrapMethodEntry;
-import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry;
-import com.sun.java.util.jar.pack.Package.Class;
-import com.sun.java.util.jar.pack.Package.InnerClass;
-import java.io.DataInputStream;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Map;
-import static com.sun.java.util.jar.pack.Constants.*;
-
-/**
- * Reader for a class file that is being incorporated into a package.
- * @author John Rose
- */
-class ClassReader {
-    int verbose;
-
-    Package pkg;
-    Class cls;
-    long inPos;
-    long constantPoolLimit = -1;
-    DataInputStream in;
-    Map<Attribute.Layout, Attribute> attrDefs;
-    Map<Attribute.Layout, String> attrCommands;
-    String unknownAttrCommand = "error";;
-
-    ClassReader(Class cls, InputStream in) throws IOException {
-        this.pkg = cls.getPackage();
-        this.cls = cls;
-        this.verbose = pkg.verbose;
-        this.in = new DataInputStream(new FilterInputStream(in) {
-            public int read(byte b[], int off, int len) throws IOException {
-                int nr = super.read(b, off, len);
-                if (nr >= 0)  inPos += nr;
-                return nr;
-            }
-            public int read() throws IOException {
-                int ch = super.read();
-                if (ch >= 0)  inPos += 1;
-                return ch;
-            }
-            public long skip(long n) throws IOException {
-                long ns = super.skip(n);
-                if (ns >= 0)  inPos += ns;
-                return ns;
-            }
-        });
-    }
-
-    public void setAttrDefs(Map<Attribute.Layout, Attribute> attrDefs) {
-        this.attrDefs = attrDefs;
-    }
-
-    public void setAttrCommands(Map<Attribute.Layout, String> attrCommands) {
-        this.attrCommands = attrCommands;
-    }
-
-    private void skip(int n, String what) throws IOException {
-        Utils.log.warning("skipping "+n+" bytes of "+what);
-        long skipped = 0;
-        while (skipped < n) {
-            long j = in.skip(n - skipped);
-            assert(j > 0);
-            skipped += j;
-        }
-        assert(skipped == n);
-    }
-
-    private int readUnsignedShort() throws IOException {
-        return in.readUnsignedShort();
-    }
-
-    private int readInt() throws IOException {
-        return in.readInt();
-    }
-
-    /** Read a 2-byte int, and return the <em>global</em> CP entry for it. */
-    private Entry readRef() throws IOException {
-        int i = in.readUnsignedShort();
-        return i == 0 ? null : cls.cpMap[i];
-    }
-
-    private Entry readRef(byte tag) throws IOException {
-        Entry e = readRef();
-        assert(!(e instanceof UnresolvedEntry));
-        checkTag(e, tag);
-        return e;
-    }
-
-    /** Throw a ClassFormatException if the entry does not match the expected tag type. */
-    private Entry checkTag(Entry e, byte tag) throws ClassFormatException {
-        if (e == null || !e.tagMatches(tag)) {
-            String where = (inPos == constantPoolLimit
-                                ? " in constant pool"
-                                : " at pos: " + inPos);
-            String got = (e == null
-                            ? "null CP index"
-                            : "type=" + ConstantPool.tagName(e.tag));
-            throw new ClassFormatException("Bad constant, expected type=" +
-                    ConstantPool.tagName(tag) +
-                    " got "+ got + ", in File: " + cls.file.nameString + where);
-        }
-        return e;
-    }
-    private Entry checkTag(Entry e, byte tag, boolean nullOK) throws ClassFormatException {
-        return nullOK && e == null ? null : checkTag(e, tag);
-    }
-
-    private Entry readRefOrNull(byte tag) throws IOException {
-        Entry e = readRef();
-        checkTag(e, tag, true);
-        return e;
-    }
-
-    private Utf8Entry readUtf8Ref() throws IOException {
-        return (Utf8Entry) readRef(CONSTANT_Utf8);
-    }
-
-    private ClassEntry readClassRef() throws IOException {
-        return (ClassEntry) readRef(CONSTANT_Class);
-    }
-
-    private ClassEntry readClassRefOrNull() throws IOException {
-        return (ClassEntry) readRefOrNull(CONSTANT_Class);
-    }
-
-    private SignatureEntry readSignatureRef() throws IOException {
-        // The class file stores a Utf8, but we want a Signature.
-        Entry e = readRef(CONSTANT_Signature);
-        return (e != null && e.getTag() == CONSTANT_Utf8)
-                ? ConstantPool.getSignatureEntry(e.stringValue())
-                : (SignatureEntry) e;
-    }
-
-    void read() throws IOException {
-        boolean ok = false;
-        try {
-            readMagicNumbers();
-            readConstantPool();
-            readHeader();
-            readMembers(false);  // fields
-            readMembers(true);   // methods
-            readAttributes(ATTR_CONTEXT_CLASS, cls);
-            fixUnresolvedEntries();
-            cls.finishReading();
-            assert(0 >= in.read(new byte[1]));
-            ok = true;
-        } finally {
-            if (!ok) {
-                if (verbose > 0) Utils.log.warning("Erroneous data at input offset "+inPos+" of "+cls.file);
-            }
-        }
-    }
-
-    void readMagicNumbers() throws IOException {
-        cls.magic = in.readInt();
-        if (cls.magic != JAVA_MAGIC)
-            throw new Attribute.FormatException
-                ("Bad magic number in class file "
-                 +Integer.toHexString(cls.magic),
-                 ATTR_CONTEXT_CLASS, "magic-number", "pass");
-        int minver = (short) readUnsignedShort();
-        int majver = (short) readUnsignedShort();
-        cls.version = Package.Version.of(majver, minver);
-
-        //System.out.println("ClassFile.version="+cls.majver+"."+cls.minver);
-        String bad = checkVersion(cls.version);
-        if (bad != null) {
-            throw new Attribute.FormatException
-                ("classfile version too "+bad+": "
-                 +cls.version+" in "+cls.file,
-                 ATTR_CONTEXT_CLASS, "version", "pass");
-        }
-    }
-
-    private String checkVersion(Package.Version ver) {
-        int majver = ver.major;
-        int minver = ver.minor;
-        if (majver < pkg.minClassVersion.major ||
-            (majver == pkg.minClassVersion.major &&
-             minver < pkg.minClassVersion.minor)) {
-            return "small";
-        }
-        if (majver > pkg.maxClassVersion.major ||
-            (majver == pkg.maxClassVersion.major &&
-             minver > pkg.maxClassVersion.minor)) {
-            return "large";
-        }
-        return null;  // OK
-    }
-
-    void readConstantPool() throws IOException {
-        int length = in.readUnsignedShort();
-        //System.err.println("reading CP, length="+length);
-
-        int[] fixups = new int[length*4];
-        int fptr = 0;
-
-        Entry[] cpMap = new Entry[length];
-        cpMap[0] = null;
-        for (int i = 1; i < length; i++) {
-            //System.err.println("reading CP elt, i="+i);
-            int tag = in.readByte();
-            switch (tag) {
-                case CONSTANT_Utf8:
-                    cpMap[i] = ConstantPool.getUtf8Entry(in.readUTF());
-                    break;
-                case CONSTANT_Integer:
-                    {
-                        cpMap[i] = ConstantPool.getLiteralEntry(in.readInt());
-                    }
-                    break;
-                case CONSTANT_Float:
-                    {
-                        cpMap[i] = ConstantPool.getLiteralEntry(in.readFloat());
-                    }
-                    break;
-                case CONSTANT_Long:
-                    {
-                        cpMap[i] = ConstantPool.getLiteralEntry(in.readLong());
-                        cpMap[++i] = null;
-                    }
-                    break;
-                case CONSTANT_Double:
-                    {
-                        cpMap[i] = ConstantPool.getLiteralEntry(in.readDouble());
-                        cpMap[++i] = null;
-                    }
-                    break;
-
-                // just read the refs; do not attempt to resolve while reading
-                case CONSTANT_Class:
-                case CONSTANT_String:
-                case CONSTANT_MethodType:
-                    fixups[fptr++] = i;
-                    fixups[fptr++] = tag;
-                    fixups[fptr++] = in.readUnsignedShort();
-                    fixups[fptr++] = -1;  // empty ref2
-                    break;
-                case CONSTANT_Fieldref:
-                case CONSTANT_Methodref:
-                case CONSTANT_InterfaceMethodref:
-                case CONSTANT_NameandType:
-                    fixups[fptr++] = i;
-                    fixups[fptr++] = tag;
-                    fixups[fptr++] = in.readUnsignedShort();
-                    fixups[fptr++] = in.readUnsignedShort();
-                    break;
-                case CONSTANT_InvokeDynamic:
-                    fixups[fptr++] = i;
-                    fixups[fptr++] = tag;
-                    fixups[fptr++] = -1 ^ in.readUnsignedShort();  // not a ref
-                    fixups[fptr++] = in.readUnsignedShort();
-                    break;
-                case CONSTANT_MethodHandle:
-                    fixups[fptr++] = i;
-                    fixups[fptr++] = tag;
-                    fixups[fptr++] = -1 ^ in.readUnsignedByte();
-                    fixups[fptr++] = in.readUnsignedShort();
-                    break;
-                default:
-                    throw new ClassFormatException("Bad constant pool tag " +
-                            tag + " in File: " + cls.file.nameString +
-                            " at pos: " + inPos);
-            }
-        }
-        constantPoolLimit = inPos;
-
-        // Fix up refs, which might be out of order.
-        while (fptr > 0) {
-            if (verbose > 3)
-                Utils.log.fine("CP fixups ["+fptr/4+"]");
-            int flimit = fptr;
-            fptr = 0;
-            for (int fi = 0; fi < flimit; ) {
-                int cpi = fixups[fi++];
-                int tag = fixups[fi++];
-                int ref = fixups[fi++];
-                int ref2 = fixups[fi++];
-                if (verbose > 3)
-                    Utils.log.fine("  cp["+cpi+"] = "+ConstantPool.tagName(tag)+"{"+ref+","+ref2+"}");
-                if (ref >= 0 && cpMap[ref] == null || ref2 >= 0 && cpMap[ref2] == null) {
-                    // Defer.
-                    fixups[fptr++] = cpi;
-                    fixups[fptr++] = tag;
-                    fixups[fptr++] = ref;
-                    fixups[fptr++] = ref2;
-                    continue;
-                }
-                switch (tag) {
-                case CONSTANT_Class:
-                    cpMap[cpi] = ConstantPool.getClassEntry(cpMap[ref].stringValue());
-                    break;
-                case CONSTANT_String:
-                    cpMap[cpi] = ConstantPool.getStringEntry(cpMap[ref].stringValue());
-                    break;
-                case CONSTANT_Fieldref:
-                case CONSTANT_Methodref:
-                case CONSTANT_InterfaceMethodref:
-                    ClassEntry      mclass = (ClassEntry)      checkTag(cpMap[ref],  CONSTANT_Class);
-                    DescriptorEntry mdescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType);
-                    cpMap[cpi] = ConstantPool.getMemberEntry((byte)tag, mclass, mdescr);
-                    break;
-                case CONSTANT_NameandType:
-                    Utf8Entry mname = (Utf8Entry) checkTag(cpMap[ref],  CONSTANT_Utf8);
-                    Utf8Entry mtype = (Utf8Entry) checkTag(cpMap[ref2], CONSTANT_Signature);
-                    cpMap[cpi] = ConstantPool.getDescriptorEntry(mname, mtype);
-                    break;
-                case CONSTANT_MethodType:
-                    cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) checkTag(cpMap[ref], CONSTANT_Signature));
-                    break;
-                case CONSTANT_MethodHandle:
-                    byte refKind = (byte)(-1 ^ ref);
-                    MemberEntry memRef = (MemberEntry) checkTag(cpMap[ref2], CONSTANT_AnyMember);
-                    cpMap[cpi] = ConstantPool.getMethodHandleEntry(refKind, memRef);
-                    break;
-                case CONSTANT_InvokeDynamic:
-                    DescriptorEntry idescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType);
-                    cpMap[cpi] = new UnresolvedEntry((byte)tag, (-1 ^ ref), idescr);
-                    // Note that ref must be resolved later, using the BootstrapMethods attribute.
-                    break;
-                default:
-                    assert(false);
-                }
-            }
-            assert(fptr < flimit);  // Must make progress.
-        }
-
-        cls.cpMap = cpMap;
-    }
-
-    private /*non-static*/
-    class UnresolvedEntry extends Entry {
-        final Object[] refsOrIndexes;
-        UnresolvedEntry(byte tag, Object... refsOrIndexes) {
-            super(tag);
-            this.refsOrIndexes = refsOrIndexes;
-            ClassReader.this.haveUnresolvedEntry = true;
-        }
-        Entry resolve() {
-            Class cls = ClassReader.this.cls;
-            Entry res;
-            switch (tag) {
-            case CONSTANT_InvokeDynamic:
-                BootstrapMethodEntry iboots = cls.bootstrapMethods.get((Integer) refsOrIndexes[0]);
-                DescriptorEntry         idescr = (DescriptorEntry) refsOrIndexes[1];
-                res = ConstantPool.getInvokeDynamicEntry(iboots, idescr);
-                break;
-            default:
-                throw new AssertionError();
-            }
-            return res;
-        }
-        private void unresolved() { throw new RuntimeException("unresolved entry has no string"); }
-        public int compareTo(Object x) { unresolved(); return 0; }
-        public boolean equals(Object x) { unresolved(); return false; }
-        protected int computeValueHash() { unresolved(); return 0; }
-        public String stringValue() { unresolved(); return toString(); }
-        public String toString() { return "(unresolved "+ConstantPool.tagName(tag)+")"; }
-    }
-
-    boolean haveUnresolvedEntry;
-    private void fixUnresolvedEntries() {
-        if (!haveUnresolvedEntry)  return;
-        Entry[] cpMap = cls.getCPMap();
-        for (int i = 0; i < cpMap.length; i++) {
-            Entry e = cpMap[i];
-            if (e instanceof UnresolvedEntry) {
-                cpMap[i] = e = ((UnresolvedEntry)e).resolve();
-                assert(!(e instanceof UnresolvedEntry));
-            }
-        }
-        haveUnresolvedEntry = false;
-    }
-
-    void readHeader() throws IOException {
-        cls.flags = readUnsignedShort();
-        cls.thisClass = readClassRef();
-        cls.superClass = readClassRefOrNull();
-        int ni = readUnsignedShort();
-        cls.interfaces = new ClassEntry[ni];
-        for (int i = 0; i < ni; i++) {
-            cls.interfaces[i] = readClassRef();
-        }
-    }
-
-    void readMembers(boolean doMethods) throws IOException {
-        int nm = readUnsignedShort();
-        for (int i = 0; i < nm; i++) {
-            readMember(doMethods);
-        }
-    }
-
-    void readMember(boolean doMethod) throws IOException {
-        int    mflags = readUnsignedShort();
-        Utf8Entry       mname = readUtf8Ref();
-        SignatureEntry  mtype = readSignatureRef();
-        DescriptorEntry descr = ConstantPool.getDescriptorEntry(mname, mtype);
-        Class.Member m;
-        if (!doMethod)
-            m = cls.new Field(mflags, descr);
-        else
-            m = cls.new Method(mflags, descr);
-        readAttributes(!doMethod ? ATTR_CONTEXT_FIELD : ATTR_CONTEXT_METHOD,
-                       m);
-    }
-    void readAttributes(int ctype, Attribute.Holder h) throws IOException {
-        int na = readUnsignedShort();
-        if (na == 0)  return;  // nothing to do here
-        if (verbose > 3)
-            Utils.log.fine("readAttributes "+h+" ["+na+"]");
-        for (int i = 0; i < na; i++) {
-            String name = readUtf8Ref().stringValue();
-            int length = readInt();
-            // See if there is a special command that applies.
-            if (attrCommands != null) {
-                Attribute.Layout lkey = Attribute.keyForLookup(ctype, name);
-                String cmd = attrCommands.get(lkey);
-                if (cmd != null) {
-                    switch (cmd) {
-                        case "pass":
-                            String message1 = "passing attribute bitwise in " + h;
-                            throw new Attribute.FormatException(message1, ctype, name, cmd);
-                        case "error":
-                            String message2 = "attribute not allowed in " + h;
-                            throw new Attribute.FormatException(message2, ctype, name, cmd);
-                        case "strip":
-                            skip(length, name + " attribute in " + h);
-                            continue;
-                    }
-                }
-            }
-            // Find canonical instance of the requested attribute.
-            Attribute a = Attribute.lookup(Package.attrDefs, ctype, name);
-            if (verbose > 4 && a != null)
-                Utils.log.fine("pkg_attribute_lookup "+name+" = "+a);
-            if (a == null) {
-                a = Attribute.lookup(this.attrDefs, ctype, name);
-                if (verbose > 4 && a != null)
-                    Utils.log.fine("this "+name+" = "+a);
-            }
-            if (a == null) {
-                a = Attribute.lookup(null, ctype, name);
-                if (verbose > 4 && a != null)
-                    Utils.log.fine("null_attribute_lookup "+name+" = "+a);
-            }
-            if (a == null && length == 0) {
-                // Any zero-length attr is "known"...
-                // We can assume an empty attr. has an empty layout.
-                // Handles markers like Enum, Bridge, Synthetic, Deprecated.
-                a = Attribute.find(ctype, name, "");
-            }
-            boolean isStackMap = (ctype == ATTR_CONTEXT_CODE
-                                  && (name.equals("StackMap") ||
-                                      name.equals("StackMapX")));
-            if (isStackMap) {
-                // Known attribute but with a corner case format, "pass" it.
-                Code code = (Code) h;
-                final int TOO_BIG = 0x10000;
-                if (code.max_stack   >= TOO_BIG ||
-                    code.max_locals  >= TOO_BIG ||
-                    code.getLength() >= TOO_BIG ||
-                    name.endsWith("X")) {
-                    // No, we don't really know what to do with this one.
-                    // Do not compress the rare and strange "u4" and "X" cases.
-                    a = null;
-                }
-            }
-            if (a == null) {
-                if (isStackMap) {
-                    // Known attribute but w/o a format; pass it.
-                    String message = "unsupported StackMap variant in "+h;
-                    throw new Attribute.FormatException(message, ctype, name,
-                                                        "pass");
-                } else if ("strip".equals(unknownAttrCommand)) {
-                    // Skip the unknown attribute.
-                    skip(length, "unknown "+name+" attribute in "+h);
-                    continue;
-                } else {
-                    String message = " is unknown attribute in class " + h;
-                    throw new Attribute.FormatException(message, ctype, name,
-                                                        unknownAttrCommand);
-                }
-            }
-            long pos0 = inPos;  // in case we want to check it
-            if (a.layout() == Package.attrCodeEmpty) {
-                // These are hardwired.
-                Class.Method m = (Class.Method) h;
-                m.code = new Code(m);
-                try {
-                    readCode(m.code);
-                } catch (Instruction.FormatException iie) {
-                    String message = iie.getMessage() + " in " + h;
-                    throw new ClassReader.ClassFormatException(message, iie);
-                }
-                assert(length == inPos - pos0);
-                // Keep empty attribute a...
-            } else if (a.layout() == Package.attrBootstrapMethodsEmpty) {
-                assert(h == cls);
-                readBootstrapMethods(cls);
-                assert(length == inPos - pos0);
-                // Delete the attribute; it is logically part of the constant pool.
-                continue;
-            } else if (a.layout() == Package.attrInnerClassesEmpty) {
-                // These are hardwired also.
-                assert(h == cls);
-                readInnerClasses(cls);
-                assert(length == inPos - pos0);
-                // Keep empty attribute a...
-            } else if (length > 0) {
-                byte[] bytes = new byte[length];
-                in.readFully(bytes);
-                a = a.addContent(bytes);
-            }
-            if (a.size() == 0 && !a.layout().isEmpty()) {
-                throw new ClassFormatException(name +
-                        ": attribute length cannot be zero, in " + h);
-            }
-            h.addAttribute(a);
-            if (verbose > 2)
-                Utils.log.fine("read "+a);
-        }
-    }
-
-    void readCode(Code code) throws IOException {
-        code.max_stack = readUnsignedShort();
-        code.max_locals = readUnsignedShort();
-        code.bytes = new byte[readInt()];
-        in.readFully(code.bytes);
-        Entry[] cpMap = cls.getCPMap();
-        Instruction.opcodeChecker(code.bytes, cpMap, this.cls.version);
-        int nh = readUnsignedShort();
-        code.setHandlerCount(nh);
-        for (int i = 0; i < nh; i++) {
-            code.handler_start[i] = readUnsignedShort();
-            code.handler_end[i]   = readUnsignedShort();
-            code.handler_catch[i] = readUnsignedShort();
-            code.handler_class[i] = readClassRefOrNull();
-        }
-        readAttributes(ATTR_CONTEXT_CODE, code);
-    }
-
-    void readBootstrapMethods(Class cls) throws IOException {
-        BootstrapMethodEntry[] bsms = new BootstrapMethodEntry[readUnsignedShort()];
-        for (int i = 0; i < bsms.length; i++) {
-            MethodHandleEntry bsmRef = (MethodHandleEntry) readRef(CONSTANT_MethodHandle);
-            Entry[] argRefs = new Entry[readUnsignedShort()];
-            for (int j = 0; j < argRefs.length; j++) {
-                argRefs[j] = readRef(CONSTANT_LoadableValue);
-            }
-            bsms[i] = ConstantPool.getBootstrapMethodEntry(bsmRef, argRefs);
-        }
-        cls.setBootstrapMethods(Arrays.asList(bsms));
-    }
-
-    void readInnerClasses(Class cls) throws IOException {
-        int nc = readUnsignedShort();
-        ArrayList<InnerClass> ics = new ArrayList<>(nc);
-        for (int i = 0; i < nc; i++) {
-            InnerClass ic =
-                new InnerClass(readClassRef(),
-                               readClassRefOrNull(),
-                               (Utf8Entry)readRefOrNull(CONSTANT_Utf8),
-                               readUnsignedShort());
-            ics.add(ic);
-        }
-        cls.innerClasses = ics;  // set directly; do not use setInnerClasses.
-        // (Later, ics may be transferred to the pkg.)
-    }
-
-    static class ClassFormatException extends IOException {
-        @java.io.Serial
-        private static final long serialVersionUID = -3564121733989501833L;
-
-        public ClassFormatException(String message) {
-            super(message);
-        }
-
-        public ClassFormatException(String message, Throwable cause) {
-            super(message, cause);
-        }
-    }
-}
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/ClassWriter.java	Mon Dec 09 15:28:46 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,317 +0,0 @@
-/*
- * Copyright (c) 2001, 2012, 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.Entry;
-import com.sun.java.util.jar.pack.ConstantPool.Index;
-import com.sun.java.util.jar.pack.ConstantPool.NumberEntry;
-import com.sun.java.util.jar.pack.ConstantPool.MethodHandleEntry;
-import com.sun.java.util.jar.pack.ConstantPool.BootstrapMethodEntry;
-import com.sun.java.util.jar.pack.Package.Class;
-import com.sun.java.util.jar.pack.Package.InnerClass;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.List;
-import static com.sun.java.util.jar.pack.Constants.*;
-/**
- * Writer for a class file that is incorporated into a package.
- * @author John Rose
- */
-class ClassWriter {
-    int verbose;
-
-    Package pkg;
-    Class cls;
-    DataOutputStream out;
-    Index cpIndex;
-    Index bsmIndex;
-
-    ClassWriter(Class cls, OutputStream out) throws IOException {
-        this.pkg = cls.getPackage();
-        this.cls = cls;
-        this.verbose = pkg.verbose;
-        this.out = new DataOutputStream(new BufferedOutputStream(out));
-        this.cpIndex = ConstantPool.makeIndex(cls.toString(), cls.getCPMap());
-        this.cpIndex.flattenSigs = true;
-        if (cls.hasBootstrapMethods()) {
-            this.bsmIndex = ConstantPool.makeIndex(cpIndex.debugName+".BootstrapMethods",
-                                                   cls.getBootstrapMethodMap());
-        }
-        if (verbose > 1)
-            Utils.log.fine("local CP="+(verbose > 2 ? cpIndex.dumpString() : cpIndex.toString()));
-    }
-
-    private void writeShort(int x) throws IOException {
-        out.writeShort(x);
-    }
-
-    private void writeInt(int x) throws IOException {
-        out.writeInt(x);
-    }
-
-    /** Write a 2-byte int representing a CP entry, using the local cpIndex. */
-    private void writeRef(Entry e) throws IOException {
-        writeRef(e, cpIndex);
-    }
-
-    /** Write a 2-byte int representing a CP entry, using the given cpIndex. */
-    private void writeRef(Entry e, Index cpIndex) throws IOException {
-        int i = (e == null) ? 0 : cpIndex.indexOf(e);
-        writeShort(i);
-    }
-
-    void write() throws IOException {
-        boolean ok = false;
-        try {
-            if (verbose > 1)  Utils.log.fine("...writing "+cls);
-            writeMagicNumbers();
-            writeConstantPool();
-            writeHeader();
-            writeMembers(false);  // fields
-            writeMembers(true);   // methods
-            writeAttributes(ATTR_CONTEXT_CLASS, cls);
-            /* Closing here will cause all the underlying
-               streams to close, Causing the jar stream
-               to close prematurely, instead we just flush.
-               out.close();
-             */
-            out.flush();
-            ok = true;
-        } finally {
-            if (!ok) {
-                Utils.log.warning("Error on output of "+cls);
-            }
-        }
-    }
-
-    void writeMagicNumbers() throws IOException {
-        writeInt(cls.magic);
-        writeShort(cls.version.minor);
-        writeShort(cls.version.major);
-    }
-
-    void writeConstantPool() throws IOException {
-        Entry[] cpMap = cls.cpMap;
-        writeShort(cpMap.length);
-        for (int i = 0; i < cpMap.length; i++) {
-            Entry e = cpMap[i];
-            assert((e == null) == (i == 0 || cpMap[i-1] != null && cpMap[i-1].isDoubleWord()));
-            if (e == null)  continue;
-            byte tag = e.getTag();
-            if (verbose > 2)  Utils.log.fine("   CP["+i+"] = "+e);
-            out.write(tag);
-            switch (tag) {
-                case CONSTANT_Signature:
-                    throw new AssertionError("CP should have Signatures remapped to Utf8");
-                case CONSTANT_Utf8:
-                    out.writeUTF(e.stringValue());
-                    break;
-                case CONSTANT_Integer:
-                    out.writeInt(((NumberEntry)e).numberValue().intValue());
-                    break;
-                case CONSTANT_Float:
-                    float fval = ((NumberEntry)e).numberValue().floatValue();
-                    out.writeInt(Float.floatToRawIntBits(fval));
-                    break;
-                case CONSTANT_Long:
-                    out.writeLong(((NumberEntry)e).numberValue().longValue());
-                    break;
-                case CONSTANT_Double:
-                    double dval = ((NumberEntry)e).numberValue().doubleValue();
-                    out.writeLong(Double.doubleToRawLongBits(dval));
-                    break;
-                case CONSTANT_Class:
-                case CONSTANT_String:
-                case CONSTANT_MethodType:
-                    writeRef(e.getRef(0));
-                    break;
-                case CONSTANT_MethodHandle:
-                    MethodHandleEntry mhe = (MethodHandleEntry) e;
-                    out.writeByte(mhe.refKind);
-                    writeRef(mhe.getRef(0));
-                    break;
-                case CONSTANT_Fieldref:
-                case CONSTANT_Methodref:
-                case CONSTANT_InterfaceMethodref:
-                case CONSTANT_NameandType:
-                    writeRef(e.getRef(0));
-                    writeRef(e.getRef(1));
-                    break;
-                case CONSTANT_InvokeDynamic:
-                    writeRef(e.getRef(0), bsmIndex);
-                    writeRef(e.getRef(1));
-                    break;
-                case CONSTANT_BootstrapMethod:
-                    throw new AssertionError("CP should have BootstrapMethods moved to side-table");
-                default:
-                    throw new IOException("Bad constant pool tag "+tag);
-            }
-        }
-    }
-
-    void writeHeader() throws IOException {
-        writeShort(cls.flags);
-        writeRef(cls.thisClass);
-        writeRef(cls.superClass);
-        writeShort(cls.interfaces.length);
-        for (int i = 0; i < cls.interfaces.length; i++) {
-            writeRef(cls.interfaces[i]);
-        }
-    }
-
-    void writeMembers(boolean doMethods) throws IOException {
-        List<? extends Class.Member> mems;
-        if (!doMethods)
-            mems = cls.getFields();
-        else
-            mems = cls.getMethods();
-        writeShort(mems.size());
-        for (Class.Member m : mems) {
-            writeMember(m, doMethods);
-        }
-    }
-
-    void writeMember(Class.Member m, boolean doMethod) throws IOException {
-        if (verbose > 2)  Utils.log.fine("writeMember "+m);
-        writeShort(m.flags);
-        writeRef(m.getDescriptor().nameRef);
-        writeRef(m.getDescriptor().typeRef);
-        writeAttributes(!doMethod ? ATTR_CONTEXT_FIELD : ATTR_CONTEXT_METHOD,
-                        m);
-    }
-
-    private void reorderBSMandICS(Attribute.Holder h) {
-        Attribute bsmAttr = h.getAttribute(Package.attrBootstrapMethodsEmpty);
-        if (bsmAttr == null) return;
-
-        Attribute icsAttr = h.getAttribute(Package.attrInnerClassesEmpty);
-        if (icsAttr == null) return;
-
-        int bsmidx = h.attributes.indexOf(bsmAttr);
-        int icsidx = h.attributes.indexOf(icsAttr);
-        if (bsmidx > icsidx) {
-            h.attributes.remove(bsmAttr);
-            h.attributes.add(icsidx, bsmAttr);
-        }
-        return;
-    }
-
-    // handy buffer for collecting attrs
-    ByteArrayOutputStream buf    = new ByteArrayOutputStream();
-    DataOutputStream      bufOut = new DataOutputStream(buf);
-
-    void writeAttributes(int ctype, Attribute.Holder h) throws IOException {
-        if (h.attributes == null) {
-            writeShort(0);  // attribute size
-            return;
-        }
-        // there may be cases if an InnerClass attribute is explicit, then the
-        // ordering could be wrong, fix the ordering before we write it out.
-        if (h instanceof Package.Class)
-            reorderBSMandICS(h);
-
-        writeShort(h.attributes.size());
-        for (Attribute a : h.attributes) {
-            a.finishRefs(cpIndex);
-            writeRef(a.getNameRef());
-            if (a.layout() == Package.attrCodeEmpty ||
-                a.layout() == Package.attrBootstrapMethodsEmpty ||
-                a.layout() == Package.attrInnerClassesEmpty) {
-                // These are hardwired.
-                DataOutputStream savedOut = out;
-                assert(out != bufOut);
-                buf.reset();
-                out = bufOut;
-                if ("Code".equals(a.name())) {
-                    Class.Method m = (Class.Method) h;
-                    writeCode(m.code);
-                } else if ("BootstrapMethods".equals(a.name())) {
-                    assert(h == cls);
-                    writeBootstrapMethods(cls);
-                } else if ("InnerClasses".equals(a.name())) {
-                    assert(h == cls);
-                    writeInnerClasses(cls);
-                } else {
-                    throw new AssertionError();
-                }
-                out = savedOut;
-                if (verbose > 2)
-                    Utils.log.fine("Attribute "+a.name()+" ["+buf.size()+"]");
-                writeInt(buf.size());
-                buf.writeTo(out);
-            } else {
-                if (verbose > 2)
-                    Utils.log.fine("Attribute "+a.name()+" ["+a.size()+"]");
-                writeInt(a.size());
-                out.write(a.bytes());
-            }
-        }
-    }
-
-    void writeCode(Code code) throws IOException {
-        code.finishRefs(cpIndex);
-        writeShort(code.max_stack);
-        writeShort(code.max_locals);
-        writeInt(code.bytes.length);
-        out.write(code.bytes);
-        int nh = code.getHandlerCount();
-        writeShort(nh);
-        for (int i = 0; i < nh; i++) {
-             writeShort(code.handler_start[i]);
-             writeShort(code.handler_end[i]);
-             writeShort(code.handler_catch[i]);
-             writeRef(code.handler_class[i]);
-        }
-        writeAttributes(ATTR_CONTEXT_CODE, code);
-    }
-
-    void writeBootstrapMethods(Class cls) throws IOException {
-        List<BootstrapMethodEntry> bsms = cls.getBootstrapMethods();
-        writeShort(bsms.size());
-        for (BootstrapMethodEntry e : bsms) {
-            writeRef(e.bsmRef);
-            writeShort(e.argRefs.length);
-            for (Entry argRef : e.argRefs) {
-                writeRef(argRef);
-            }
-        }
-    }
-
-    void writeInnerClasses(Class cls) throws IOException {
-        List<InnerClass> ics = cls.getInnerClasses();
-        writeShort(ics.size());
-        for (InnerClass ic : ics) {
-            writeRef(ic.thisClass);
-            writeRef(ic.outerClass);
-            writeRef(ic.name);
-            writeShort(ic.flags);
-        }
-    }
-}
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/Code.java	Mon Dec 09 15:28:46 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,398 +0,0 @@
-/*
- * Copyright (c) 2001, 2013, 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.Package.Class;
-import java.lang.reflect.Modifier;
-import java.util.Arrays;
-import java.util.Collection;
-import static com.sun.java.util.jar.pack.Constants.*;
-
-/**
- * Represents a chunk of bytecodes.
- * @author John Rose
- */
-class Code extends Attribute.Holder {
-    Class.Method m;
-
-    public Code(Class.Method m) {
-        this.m = m;
-    }
-
-    public Class.Method getMethod() {
-        return m;
-    }
-    public Class thisClass() {
-        return m.thisClass();
-    }
-    public Package getPackage() {
-        return m.thisClass().getPackage();
-    }
-
-    public ConstantPool.Entry[] getCPMap() {
-        return m.getCPMap();
-    }
-
-    private static final ConstantPool.Entry[] noRefs = ConstantPool.noRefs;
-
-    // The following fields are used directly by the ClassReader, etc.
-    int max_stack;
-    int max_locals;
-
-    ConstantPool.Entry handler_class[] = noRefs;
-    int handler_start[] = noInts;
-    int handler_end[] = noInts;
-    int handler_catch[] = noInts;
-
-    byte[] bytes;
-    Fixups fixups;  // reference relocations, if any are required
-    Object insnMap; // array of instruction boundaries
-
-    int getLength() { return bytes.length; }
-
-    int getMaxStack() {
-        return max_stack;
-    }
-    void setMaxStack(int ms) {
-        max_stack = ms;
-    }
-
-    int getMaxNALocals() {
-        int argsize = m.getArgumentSize();
-        return max_locals - argsize;
-    }
-    void setMaxNALocals(int ml) {
-        int argsize = m.getArgumentSize();
-        max_locals = argsize + ml;
-    }
-
-    int getHandlerCount() {
-        assert(handler_class.length == handler_start.length);
-        assert(handler_class.length == handler_end.length);
-        assert(handler_class.length == handler_catch.length);
-        return handler_class.length;
-    }
-    void setHandlerCount(int h) {
-        if (h > 0) {
-            handler_class = new ConstantPool.Entry[h];
-            handler_start = new int[h];
-            handler_end   = new int[h];
-            handler_catch = new int[h];
-            // caller must fill these in ASAP
-        }
-    }
-
-    void setBytes(byte[] bytes) {
-        this.bytes = bytes;
-        if (fixups != null)
-            fixups.setBytes(bytes);
-    }
-
-    void setInstructionMap(int[] insnMap, int mapLen) {
-        //int[] oldMap = null;
-        //assert((oldMap = getInstructionMap()) != null);
-        this.insnMap = allocateInstructionMap(insnMap, mapLen);
-        //assert(Arrays.equals(oldMap, getInstructionMap()));
-    }
-    void setInstructionMap(int[] insnMap) {
-        setInstructionMap(insnMap, insnMap.length);
-    }
-
-    int[] getInstructionMap() {
-        return expandInstructionMap(getInsnMap());
-    }
-
-    void addFixups(Collection<Fixups.Fixup> moreFixups) {
-        if (fixups == null) {
-            fixups = new Fixups(bytes);
-        }
-        assert(fixups.getBytes() == bytes);
-        fixups.addAll(moreFixups);
-    }
-
-    public void trimToSize() {
-        if (fixups != null) {
-            fixups.trimToSize();
-            if (fixups.size() == 0)
-                fixups = null;
-        }
-        super.trimToSize();
-    }
-
-    protected void visitRefs(int mode, Collection<ConstantPool.Entry> refs) {
-        int verbose = getPackage().verbose;
-        if (verbose > 2)
-            System.out.println("Reference scan "+this);
-        refs.addAll(Arrays.asList(handler_class));
-        if (fixups != null) {
-            fixups.visitRefs(refs);
-        } else {
-            // References (to a local cpMap) are embedded in the bytes.
-            ConstantPool.Entry[] cpMap = getCPMap();
-            for (Instruction i = instructionAt(0); i != null; i = i.next()) {
-                if (verbose > 4)
-                    System.out.println(i);
-                int cpref = i.getCPIndex();
-                if (cpref >= 0) {
-                    refs.add(cpMap[cpref]);
-                }
-            }
-        }
-        // Handle attribute list:
-        super.visitRefs(mode, refs);
-    }
-
-    // Since bytecodes are the single largest contributor to
-    // package size, it's worth a little bit of trouble
-    // to reduce the per-bytecode memory footprint.
-    // In the current scheme, half of the bulk of these arrays
-    // due to bytes, and half to shorts.  (Ints are insignificant.)
-    // Given an average of 1.8 bytes per instruction, this means
-    // instruction boundary arrays are about a 75% overhead--tolerable.
-    // (By using bytes, we get 33% savings over just shorts and ints.
-    // Using both bytes and shorts gives 66% savings over just ints.)
-    static final boolean shrinkMaps = true;
-
-    private Object allocateInstructionMap(int[] insnMap, int mapLen) {
-        int PClimit = getLength();
-        if (shrinkMaps && PClimit <= Byte.MAX_VALUE - Byte.MIN_VALUE) {
-            byte[] map = new byte[mapLen+1];
-            for (int i = 0; i < mapLen; i++) {
-                map[i] = (byte)(insnMap[i] + Byte.MIN_VALUE);
-            }
-            map[mapLen] = (byte)(PClimit + Byte.MIN_VALUE);
-            return map;
-        } else if (shrinkMaps && PClimit < Short.MAX_VALUE - Short.MIN_VALUE) {
-            short[] map = new short[mapLen+1];
-            for (int i = 0; i < mapLen; i++) {
-                map[i] = (short)(insnMap[i] + Short.MIN_VALUE);
-            }
-            map[mapLen] = (short)(PClimit + Short.MIN_VALUE);
-            return map;
-        } else {
-            int[] map = Arrays.copyOf(insnMap, mapLen + 1);
-            map[mapLen] = PClimit;
-            return map;
-        }
-    }
-    private int[] expandInstructionMap(Object map0) {
-        int[] imap;
-        if (map0 instanceof byte[]) {
-            byte[] map = (byte[]) map0;
-            imap = new int[map.length-1];
-            for (int i = 0; i < imap.length; i++) {
-                imap[i] = map[i] - Byte.MIN_VALUE;
-            }
-        } else if (map0 instanceof short[]) {
-            short[] map = (short[]) map0;
-            imap = new int[map.length-1];
-            for (int i = 0; i < imap.length; i++) {
-                imap[i] = map[i] - Byte.MIN_VALUE;
-            }
-        } else {
-            int[] map = (int[]) map0;
-            imap = Arrays.copyOfRange(map, 0, map.length - 1);
-        }
-        return imap;
-    }
-
-    Object getInsnMap() {
-        // Build a map of instruction boundaries.
-        if (insnMap != null) {
-            return insnMap;
-        }
-        int[] map = new int[getLength()];
-        int fillp = 0;
-        for (Instruction i = instructionAt(0); i != null; i = i.next()) {
-            map[fillp++] = i.getPC();
-        }
-        // Make it byte[], short[], or int[] according to the max BCI.
-        insnMap = allocateInstructionMap(map, fillp);
-        //assert(assertBCICodingsOK());
-        return insnMap;
-    }
-
-    /** Encode the given BCI as an instruction boundary number.
-     *  For completeness, irregular (non-boundary) BCIs are
-     *  encoded compactly immediately after the boundary numbers.
-     *  This encoding is the identity mapping outside 0..length,
-     *  and it is 1-1 everywhere.  All by itself this technique
-     *  improved zipped rt.jar compression by 2.6%.
-     */
-    public int encodeBCI(int bci) {
-        if (bci <= 0 || bci > getLength())  return bci;
-        Object map0 = getInsnMap();
-        int i, len;
-        if (shrinkMaps && map0 instanceof byte[]) {
-            byte[] map = (byte[]) map0;
-            len = map.length;
-            i = Arrays.binarySearch(map, (byte)(bci + Byte.MIN_VALUE));
-        } else if (shrinkMaps && map0 instanceof short[]) {
-            short[] map = (short[]) map0;
-            len = map.length;
-            i = Arrays.binarySearch(map, (short)(bci + Short.MIN_VALUE));
-        } else {
-            int[] map = (int[]) map0;
-            len = map.length;
-            i = Arrays.binarySearch(map, bci);
-        }
-        assert(i != -1);
-        assert(i != 0);
-        assert(i != len);
-        assert(i != -len-1);
-        return (i >= 0) ? i : len + bci - (-i-1);
-    }
-    public int decodeBCI(int bciCode) {
-        if (bciCode <= 0 || bciCode > getLength())  return bciCode;
-        Object map0 = getInsnMap();
-        int i, len;
-        // len == map.length
-        // If bciCode < len, result is map[bciCode], the common and fast case.
-        // Otherwise, let map[i] be the smallest map[*] larger than bci.
-        // Then, required by the return statement of encodeBCI:
-        //   bciCode == len + bci - i
-        // Thus:
-        //   bci-i == bciCode-len
-        //   map[i]-adj-i == bciCode-len ; adj in (0..map[i]-map[i-1])
-        // We can solve this by searching for adjacent entries
-        // map[i-1], map[i] such that:
-        //   map[i-1]-(i-1) <= bciCode-len < map[i]-i
-        // This can be approximated by searching map[i] for bciCode and then
-        // linear searching backward.  Given the right i, we then have:
-        //   bci == bciCode-len + i
-        // This linear search is at its worst case for indexes in the beginning
-        // of a large method, but it's not clear that this is a problem in
-        // practice, since BCIs are usually on instruction boundaries.
-        if (shrinkMaps && map0 instanceof byte[]) {
-            byte[] map = (byte[]) map0;
-            len = map.length;
-            if (bciCode < len)
-                return map[bciCode] - Byte.MIN_VALUE;
-            i = Arrays.binarySearch(map, (byte)(bciCode + Byte.MIN_VALUE));
-            if (i < 0)  i = -i-1;
-            int key = bciCode-len + Byte.MIN_VALUE;
-            for (;; i--) {
-                if (map[i-1]-(i-1) <= key)  break;
-            }
-        } else if (shrinkMaps && map0 instanceof short[]) {
-            short[] map = (short[]) map0;
-            len = map.length;
-            if (bciCode < len)
-                return map[bciCode] - Short.MIN_VALUE;
-            i = Arrays.binarySearch(map, (short)(bciCode + Short.MIN_VALUE));
-            if (i < 0)  i = -i-1;
-            int key = bciCode-len + Short.MIN_VALUE;
-            for (;; i--) {
-                if (map[i-1]-(i-1) <= key)  break;
-            }
-        } else {
-            int[] map = (int[]) map0;
-            len = map.length;
-            if (bciCode < len)
-                return map[bciCode];
-            i = Arrays.binarySearch(map, bciCode);
-            if (i < 0)  i = -i-1;
-            int key = bciCode-len;
-            for (;; i--) {
-                if (map[i-1]-(i-1) <= key)  break;
-            }
-        }
-        return bciCode-len + i;
-    }
-
-    public void finishRefs(ConstantPool.Index ix) {
-        if (fixups != null) {
-            fixups.finishRefs(ix);
-            fixups = null;
-        }
-        // Code attributes are finished in ClassWriter.writeAttributes.
-    }
-
-    Instruction instructionAt(int pc) {
-        return Instruction.at(bytes, pc);
-    }
-
-    static boolean flagsRequireCode(int flags) {
-        // A method's flags force it to have a Code attribute,
-        // if the flags are neither native nor abstract.
-        return (flags & (Modifier.NATIVE | Modifier.ABSTRACT)) == 0;
-    }
-
-    public String toString() {
-        return m+".Code";
-    }
-
-    /// Fetching values from my own array.
-    public int getInt(int pc)    { return Instruction.getInt(bytes, pc); }
-    public int getShort(int pc)  { return Instruction.getShort(bytes, pc); }
-    public int getByte(int pc)   { return Instruction.getByte(bytes, pc); }
-    void setInt(int pc, int x)   { Instruction.setInt(bytes, pc, x); }
-    void setShort(int pc, int x) { Instruction.setShort(bytes, pc, x); }
-    void setByte(int pc, int x)  { Instruction.setByte(bytes, pc, x); }
-
-/* TEST CODE ONLY
-    private boolean assertBCICodingsOK() {
-        boolean ok = true;
-        int len = java.lang.reflect.Array.getLength(insnMap);
-        int base = 0;
-        if (insnMap.getClass().getComponentType() == Byte.TYPE)
-            base = Byte.MIN_VALUE;
-        if (insnMap.getClass().getComponentType() == Short.TYPE)
-            base = Short.MIN_VALUE;
-        for (int i = -1, imax = getLength()+1; i <= imax; i++) {
-            int bci = i;
-            int enc = Math.min(-999, bci-1);
-            int dec = enc;
-            try {
-                enc = encodeBCI(bci);
-                dec = decodeBCI(enc);
-            } catch (RuntimeException ee) {
-                ee.printStackTrace();
-            }
-            if (dec == bci) {
-                //System.out.println("BCI="+bci+(enc<len?"":"   ")+" enc="+enc);
-                continue;
-            }
-            if (ok) {
-                for (int q = 0; q <= 1; q++) {
-                    StringBuffer sb = new StringBuffer();
-                    sb.append("bci "+(q==0?"map":"del")+"["+len+"] = {");
-                    for (int j = 0; j < len; j++) {
-                        int mapi = ((Number)java.lang.reflect.Array.get(insnMap, j)).intValue() - base;
-                        mapi -= j*q;
-                        sb.append(" "+mapi);
-                    }
-                    sb.append(" }");
-                    System.out.println("*** "+sb);
-                }
-            }
-            System.out.println("*** BCI="+bci+" enc="+enc+" dec="+dec);
-            ok = false;
-        }
-        return ok;
-    }
-//*/
-}
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/Coding.java	Mon Dec 09 15:28:46 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,906 +0,0 @@
-/*
- * Copyright (c) 2001, 2011, 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 java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.HashMap;
-import java.util.Map;
-import static com.sun.java.util.jar.pack.Constants.*;
-/**
- * Define the conversions between sequences of small integers and raw bytes.
- * This is a schema of encodings which incorporates varying lengths,
- * varying degrees of length variability, and varying amounts of signed-ness.
- * @author John Rose
- */
-class Coding implements Comparable<Coding>, CodingMethod, Histogram.BitMetric {
-    /*
-      Coding schema for single integers, parameterized by (B,H,S):
-
-      Let B in [1,5], H in [1,256], S in [0,3].
-      (S limit is arbitrary.  B follows the 32-bit limit.  H is byte size.)
-
-      A given (B,H,S) code varies in length from 1 to B bytes.
-
-      The 256 values a byte may take on are divided into L=(256-H) and H
-      values, with all the H values larger than the L values.
-      (That is, the L values are [0,L) and the H are [L,256).)
-
-      The last byte is always either the B-th byte, a byte with "L value"
-      (<L), or both.  There is no other byte that satisfies these conditions.
-      All bytes before the last always have "H values" (>=L).
-
-      Therefore, if L==0, the code always has the full length of B bytes.
-      The coding then becomes a classic B-byte little-endian unsigned integer.
-      (Also, if L==128, the high bit of each byte acts signals the presence
-      of a following byte, up to the maximum length.)
-
-      In the unsigned case (S==0), the coding is compact and monotonic
-      in the ordering of byte sequences defined by appending zero bytes
-      to pad them to a common length B, reversing them, and ordering them
-      lexicographically.  (This agrees with "little-endian" byte order.)
-
-      Therefore, the unsigned value of a byte sequence may be defined as:
-      <pre>
-        U(b0)           == b0
-                           in [0..L)
-                           or [0..256) if B==1 (**)
-
-        U(b0,b1)        == b0 + b1*H
-                           in [L..L*(1+H))
-                           or [L..L*(1+H) + H^2) if B==2
-
-        U(b0,b1,b2)     == b0 + b1*H + b2*H^2
-                           in [L*(1+H)..L*(1+H+H^2))
-                           or [L*(1+H)..L*(1+H+H^2) + H^3) if B==3
-
-        U(b[i]: i<n)    == Sum[i<n]( b[i] * H^i )
-                           up to  L*Sum[i<n]( H^i )
-                           or to  L*Sum[i<n]( H^i ) + H^n if n==B
-      </pre>
-
-      (**) If B==1, the values H,L play no role in the coding.
-      As a convention, we require that any (1,H,S) code must always
-      encode values less than H.  Thus, a simple unsigned byte is coded
-      specifically by the code (1,256,0).
-
-      (Properly speaking, the unsigned case should be parameterized as
-      S==Infinity.  If the schema were regular, the case S==0 would really
-      denote a numbering in which all coded values are negative.)
-
-      If S>0, the unsigned value of a byte sequence is regarded as a binary
-      integer.  If any of the S low-order bits are zero, the corresponding
-      signed value will be non-negative.  If all of the S low-order bits
-      (S>0) are one, the corresponding signed value will be negative.
-
-      The non-negative signed values are compact and monotonically increasing
-      (from 0) in the ordering of the corresponding unsigned values.
-
-      The negative signed values are compact and monotonically decreasing
-      (from -1) in the ordering of the corresponding unsigned values.
-
-      In essence, the low-order S bits function as a collective sign bit
-      for negative signed numbers, and as a low-order base-(2^S-1) digit
-      for non-negative signed numbers.
-
-      Therefore, the signed value corresponding to an unsigned value is:
-      <pre>
-        Sgn(x)  == x                               if S==0
-        Sgn(x)  == (x / 2^S)*(2^S-1) + (x % 2^S),  if S>0, (x % 2^S) < 2^S-1
-        Sgn(x)  == -(x / 2^S)-1,                   if S>0, (x % 2^S) == 2^S-1
-      </pre>
-
-      Finally, the value of a byte sequence, given the coding parameters
-      (B,H,S), is defined as:
-      <pre>
-        V(b[i]: i<n)  == Sgn(U(b[i]: i<n))
-      </pre>
-
-      The extremal positive and negative signed value for a given range
-      of unsigned values may be found by sign-encoding the largest unsigned
-      value which is not 2^S-1 mod 2^S, and that which is, respectively.
-
-      Because B,H,S are variable, this is not a single coding but a schema
-      of codings.  For optimal compression, it is necessary to adaptively
-      select specific codings to the data being compressed.
-
-      For example, if a sequence of values happens never to be negative,
-      S==0 is the best choice.  If the values are equally balanced between
-      negative and positive, S==1.  If negative values are rare, then S>1
-      is more appropriate.
-
-      A (B,H,S) encoding is called a "subrange" if it does not encode
-      the largest 32-bit value, and if the number R of values it does
-      encode can be expressed as a positive 32-bit value.  (Note that
-      B=1 implies R<=256, B=2 implies R<=65536, etc.)
-
-      A delta version of a given (B,H,S) coding encodes an array of integers
-      by writing their successive differences in the (B,H,S) coding.
-      The original integers themselves may be recovered by making a
-      running accumulation of sum of the differences as they are read.
-
-      As a special case, if a (B,H,S) encoding is a subrange, its delta
-      version will only encode arrays of numbers in the coding's unsigned
-      range, [0..R-1].  The coding of deltas is still in the normal signed
-      range, if S!=0.  During delta encoding, all subtraction results are
-      reduced to the signed range, by adding multiples of R.  Likewise,
-.     during encoding, all addition results are reduced to the unsigned range.
-      This special case for subranges allows the benefits of wraparound
-      when encoding correlated sequences of very small positive numbers.
-     */
-
-    // Code-specific limits:
-    private static int saturate32(long x) {
-        if (x > Integer.MAX_VALUE)   return Integer.MAX_VALUE;
-        if (x < Integer.MIN_VALUE)   return Integer.MIN_VALUE;
-        return (int)x;
-    }
-    private static long codeRangeLong(int B, int H) {
-        return codeRangeLong(B, H, B);
-    }
-    private static long codeRangeLong(int B, int H, int nMax) {
-        // Code range for a all (B,H) codes of length <=nMax (<=B).
-        // n < B:   L*Sum[i<n]( H^i )
-        // n == B:  L*Sum[i<B]( H^i ) + H^B
-        assert(nMax >= 0 && nMax <= B);
-        assert(B >= 1 && B <= 5);
-        assert(H >= 1 && H <= 256);
-        if (nMax == 0)  return 0;  // no codes of zero length
-        if (B == 1)     return H;  // special case; see (**) above
-        int L = 256-H;
-        long sum = 0;
-        long H_i = 1;
-        for (int n = 1; n <= nMax; n++) {
-            sum += H_i;
-            H_i *= H;
-        }
-        sum *= L;
-        if (nMax == B)
-            sum += H_i;
-        return sum;
-    }
-    /** Largest int representable by (B,H,S) in up to nMax bytes. */
-    public static int codeMax(int B, int H, int S, int nMax) {
-        //assert(S >= 0 && S <= S_MAX);
-        long range = codeRangeLong(B, H, nMax);
-        if (range == 0)
-            return -1;  // degenerate max value for empty set of codes
-        if (S == 0 || range >= (long)1<<32)
-            return saturate32(range-1);
-        long maxPos = range-1;
-        while (isNegativeCode(maxPos, S)) {
-            --maxPos;
-        }
-        if (maxPos < 0)  return -1;  // No positive codings at all.
-        int smax = decodeSign32(maxPos, S);
-        // check for 32-bit wraparound:
-        if (smax < 0)
-            return Integer.MAX_VALUE;
-        return smax;
-    }
-    /** Smallest int representable by (B,H,S) in up to nMax bytes.
-        Returns Integer.MIN_VALUE if 32-bit wraparound covers
-        the entire negative range.
-     */
-    public static int codeMin(int B, int H, int S, int nMax) {
-        //assert(S >= 0 && S <= S_MAX);
-        long range = codeRangeLong(B, H, nMax);
-        if (range >= (long)1<<32 && nMax == B) {
-            // Can code negative values via 32-bit wraparound.
-            return Integer.MIN_VALUE;
-        }
-        if (S == 0) {
-            return 0;
-        }
-        long maxNeg = range-1;
-        while (!isNegativeCode(maxNeg, S))
-            --maxNeg;
-
-        if (maxNeg < 0)  return 0;  // No negative codings at all.
-        return decodeSign32(maxNeg, S);
-    }
-
-    // Some of the arithmetic below is on unsigned 32-bit integers.
-    // These must be represented in Java as longs in the range [0..2^32-1].
-    // The conversion to a signed int is just the Java cast (int), but
-    // the conversion to an unsigned int is the following little method:
-    private static long toUnsigned32(int sx) {
-        return ((long)sx << 32) >>> 32;
-    }
-
-    // Sign encoding:
-    private static boolean isNegativeCode(long ux, int S) {
-        assert(S > 0);
-        assert(ux >= -1);  // can be out of 32-bit range; who cares
-        int Smask = (1<<S)-1;
-        return (((int)ux+1) & Smask) == 0;
-    }
-    private static boolean hasNegativeCode(int sx, int S) {
-        assert(S > 0);
-        // If S>=2 very low negatives are coded by 32-bit-wrapped positives.
-        // The lowest negative representable by a negative coding is
-        // ~(umax32 >> S), and the next lower number is coded by wrapping
-        // the highest positive:
-        //    CodePos(umax32-1)  ->  (umax32-1)-((umax32-1)>>S)
-        // which simplifies to ~(umax32 >> S)-1.
-        return (0 > sx) && (sx >= ~(-1>>>S));
-    }
-    private static int decodeSign32(long ux, int S) {
-        assert(ux == toUnsigned32((int)ux))  // must be unsigned 32-bit number
-            : (Long.toHexString(ux));
-        if (S == 0) {
-            return (int) ux;  // cast to signed int
-        }
-        int sx;
-        if (isNegativeCode(ux, S)) {
-            // Sgn(x)  == -(x / 2^S)-1
-            sx = ~((int)ux >>> S);
-        } else {
-            // Sgn(x)  == (x / 2^S)*(2^S-1) + (x % 2^S)
-            sx = (int)ux - ((int)ux >>> S);
-        }
-        // Assert special case of S==1:
-        assert(!(S == 1) || sx == (((int)ux >>> 1) ^ -((int)ux & 1)));
-        return sx;
-    }
-    private static long encodeSign32(int sx, int S) {
-        if (S == 0) {
-            return toUnsigned32(sx);  // unsigned 32-bit int
-        }
-        int Smask = (1<<S)-1;
-        long ux;
-        if (!hasNegativeCode(sx, S)) {
-            // InvSgn(sx) = (sx / (2^S-1))*2^S + (sx % (2^S-1))
-            ux = sx + (toUnsigned32(sx) / Smask);
-        } else {
-            // InvSgn(sx) = (-sx-1)*2^S + (2^S-1)
-            ux = (-sx << S) - 1;
-        }
-        ux = toUnsigned32((int)ux);
-        assert(sx == decodeSign32(ux, S))
-            : (Long.toHexString(ux)+" -> "+
-               Integer.toHexString(sx)+" != "+
-               Integer.toHexString(decodeSign32(ux, S)));
-        return ux;
-    }
-
-    // Top-level coding of single integers:
-    public static void writeInt(byte[] out, int[] outpos, int sx, int B, int H, int S) {
-        long ux = encodeSign32(sx, S);
-        assert(ux == toUnsigned32((int)ux));
-        assert(ux < codeRangeLong(B, H))
-            : Long.toHexString(ux);
-        int L = 256-H;
-        long sum = ux;
-        int pos = outpos[0];
-        for (int i = 0; i < B-1; i++) {
-            if (sum < L)
-                break;
-            sum -= L;
-            int b_i = (int)( L + (sum % H) );
-            sum /= H;
-            out[pos++] = (byte)b_i;
-        }
-        out[pos++] = (byte)sum;
-        // Report number of bytes written by updating outpos[0]:
-        outpos[0] = pos;
-        // Check right away for mis-coding.
-        //assert(sx == readInt(out, new int[1], B, H, S));
-    }
-    public static int readInt(byte[] in, int[] inpos, int B, int H, int S) {
-        // U(b[i]: i<n) == Sum[i<n]( b[i] * H^i )
-        int L = 256-H;
-        long sum = 0;
-        long H_i = 1;
-        int pos = inpos[0];
-        for (int i = 0; i < B; i++) {
-            int b_i = in[pos++] & 0xFF;
-            sum += b_i*H_i;
-            H_i *= H;
-            if (b_i < L)  break;
-        }
-        //assert(sum >= 0 && sum < codeRangeLong(B, H));
-        // Report number of bytes read by updating inpos[0]:
-        inpos[0] = pos;
-        return decodeSign32(sum, S);
-    }
-    // The Stream version doesn't fetch a byte unless it is needed for coding.
-    public static int readIntFrom(InputStream in, int B, int H, int S) throws IOException {
-        // U(b[i]: i<n) == Sum[i<n]( b[i] * H^i )
-        int L = 256-H;
-        long sum = 0;
-        long H_i = 1;
-        for (int i = 0; i < B; i++) {
-            int b_i = in.read();
-            if (b_i < 0)  throw new RuntimeException("unexpected EOF");
-            sum += b_i*H_i;
-            H_i *= H;
-            if (b_i < L)  break;
-        }
-        assert(sum >= 0 && sum < codeRangeLong(B, H));
-        return decodeSign32(sum, S);
-    }
-
-    public static final int B_MAX = 5;    /* B: [1,5] */
-    public static final int H_MAX = 256;  /* H: [1,256] */
-    public static final int S_MAX = 2;    /* S: [0,2] */
-
-    // END OF STATICS.
-
-    private final int B; /*1..5*/       // # bytes (1..5)
-    private final int H; /*1..256*/     // # codes requiring a higher byte
-    private final int L; /*0..255*/     // # codes requiring a higher byte
-    private final int S; /*0..3*/       // # low-order bits representing sign
-    private final int del; /*0..2*/     // type of delta encoding (0 == none)
-    private final int min;              // smallest representable value
-    private final int max;              // largest representable value
-    private final int umin;             // smallest representable uns. value
-    private final int umax;             // largest representable uns. value
-    private final int[] byteMin;        // smallest repr. value, given # bytes
-    private final int[] byteMax;        // largest repr. value, given # bytes
-
-    private Coding(int B, int H, int S) {
-        this(B, H, S, 0);
-    }
-    private Coding(int B, int H, int S, int del) {
-        this.B = B;
-        this.H = H;
-        this.L = 256-H;
-        this.S = S;
-        this.del = del;
-        this.min = codeMin(B, H, S, B);
-        this.max = codeMax(B, H, S, B);
-        this.umin = codeMin(B, H, 0, B);
-        this.umax = codeMax(B, H, 0, B);
-        this.byteMin = new int[B];
-        this.byteMax = new int[B];
-
-        for (int nMax = 1; nMax <= B; nMax++) {
-            byteMin[nMax-1] = codeMin(B, H, S, nMax);
-            byteMax[nMax-1] = codeMax(B, H, S, nMax);
-        }
-    }
-
-    public boolean equals(Object x) {
-        if (!(x instanceof Coding))  return false;
-        Coding that = (Coding) x;
-        if (this.B != that.B)  return false;
-        if (this.H != that.H)  return false;
-        if (this.S != that.S)  return false;
-        if (this.del != that.del)  return false;
-        return true;
-    }
-
-    public int hashCode() {
-        return (del<<14)+(S<<11)+(B<<8)+(H<<0);
-    }
-
-    private static Map<Coding, Coding> codeMap;
-
-    private static synchronized Coding of(int B, int H, int S, int del) {
-        if (codeMap == null)  codeMap = new HashMap<>();
-        Coding x0 = new Coding(B, H, S, del);
-        Coding x1 = codeMap.get(x0);
-        if (x1 == null)  codeMap.put(x0, x1 = x0);
-        return x1;
-    }
-
-    public static Coding of(int B, int H) {
-        return of(B, H, 0, 0);
-    }
-
-    public static Coding of(int B, int H, int S) {
-        return of(B, H, S, 0);
-    }
-
-    public boolean canRepresentValue(int x) {
-        if (isSubrange())
-            return canRepresentUnsigned(x);
-        else
-            return canRepresentSigned(x);
-    }
-    /** Can this coding represent a single value, possibly a delta?
-     *  This ignores the D property.  That is, for delta codings,
-     *  this tests whether a delta value of 'x' can be coded.
-     *  For signed delta codings which produce unsigned end values,
-     *  use canRepresentUnsigned.
-     */
-    public boolean canRepresentSigned(int x) {
-        return (x >= min && x <= max);
-    }
-    /** Can this coding, apart from its S property,
-     *  represent a single value?  (Negative values
-     *  can only be represented via 32-bit overflow,
-     *  so this returns true for negative values
-     *  if isFullRange is true.)
-     */
-    public boolean canRepresentUnsigned(int x) {
-        return (x >= umin && x <= umax);
-    }
-
-    // object-oriented code/decode
-    public int readFrom(byte[] in, int[] inpos) {
-        return readInt(in, inpos, B, H, S);
-    }
-    public void writeTo(byte[] out, int[] outpos, int x) {
-        writeInt(out, outpos, x, B, H, S);
-    }
-
-    // Stream versions
-    public int readFrom(InputStream in) throws IOException {
-        return readIntFrom(in, B, H, S);
-    }
-    public void writeTo(OutputStream out, int x) throws IOException {
-        byte[] buf = new byte[B];
-        int[] pos = new int[1];
-        writeInt(buf, pos, x, B, H, S);
-        out.write(buf, 0, pos[0]);
-    }
-
-    // Stream/array versions
-    public void readArrayFrom(InputStream in, int[] a, int start, int end) throws IOException {
-        // %%% use byte[] buffer
-        for (int i = start; i < end; i++)
-            a[i] = readFrom(in);
-
-        for (int dstep = 0; dstep < del; dstep++) {
-            long state = 0;
-            for (int i = start; i < end; i++) {
-                state += a[i];
-                // Reduce array values to the required range.
-                if (isSubrange()) {
-                    state = reduceToUnsignedRange(state);
-                }
-                a[i] = (int) state;
-            }
-        }
-    }
-    public void writeArrayTo(OutputStream out, int[] a, int start, int end) throws IOException {
-        if (end <= start)  return;
-        for (int dstep = 0; dstep < del; dstep++) {
-            int[] deltas;
-            if (!isSubrange())
-                deltas = makeDeltas(a, start, end, 0, 0);
-            else
-                deltas = makeDeltas(a, start, end, min, max);
-            a = deltas;
-            start = 0;
-            end = deltas.length;
-        }
-        // The following code is a buffered version of this loop:
-        //    for (int i = start; i < end; i++)
-        //        writeTo(out, a[i]);
-        byte[] buf = new byte[1<<8];
-        final int bufmax = buf.length-B;
-        int[] pos = { 0 };
-        for (int i = start; i < end; ) {
-            while (pos[0] <= bufmax) {
-                writeTo(buf, pos, a[i++]);
-                if (i >= end)  break;
-            }
-            out.write(buf, 0, pos[0]);
-            pos[0] = 0;
-        }
-    }
-
-    /** Tell if the range of this coding (number of distinct
-     *  representable values) can be expressed in 32 bits.
-     */
-    boolean isSubrange() {
-        return max < Integer.MAX_VALUE
-            && ((long)max - (long)min + 1) <= Integer.MAX_VALUE;
-    }
-
-    /** Tell if this coding can represent all 32-bit values.
-     *  Note:  Some codings, such as unsigned ones, can be neither
-     *  subranges nor full-range codings.
-     */
-    boolean isFullRange() {
-        return max == Integer.MAX_VALUE && min == Integer.MIN_VALUE;
-    }
-
-    /** Return the number of values this coding (a subrange) can represent. */
-    int getRange() {
-        assert(isSubrange());
-        return (max - min) + 1;  // range includes both min & max
-    }
-
-    Coding setB(int B) { return Coding.of(B, H, S, del); }
-    Coding setH(int H) { return Coding.of(B, H, S, del); }
-    Coding setS(int S) { return Coding.of(B, H, S, del); }
-    Coding setL(int L) { return setH(256-L); }
-    Coding setD(int del) { return Coding.of(B, H, S, del); }
-    Coding getDeltaCoding() { return setD(del+1); }
-
-    /** Return a coding suitable for representing summed, modulo-reduced values. */
-    Coding getValueCoding() {
-        if (isDelta())
-            return Coding.of(B, H, 0, del-1);
-        else
-            return this;
-    }
-
-    /** Reduce the given value to be within this coding's unsigned range,
-     *  by adding or subtracting a multiple of (max-min+1).
-     */
-    int reduceToUnsignedRange(long value) {
-        if (value == (int)value && canRepresentUnsigned((int)value))
-            // already in unsigned range
-            return (int)value;
-        int range = getRange();
-        assert(range > 0);
-        value %= range;
-        if (value < 0)  value += range;
-        assert(canRepresentUnsigned((int)value));
-        return (int)value;
-    }
-
-    int reduceToSignedRange(int value) {
-        if (canRepresentSigned(value))
-            // already in signed range
-            return value;
-        return reduceToSignedRange(value, min, max);
-    }
-    static int reduceToSignedRange(int value, int min, int max) {
-        int range = (max-min+1);
-        assert(range > 0);
-        int value0 = value;
-        value -= min;
-        if (value < 0 && value0 >= 0) {
-            // 32-bit overflow, but the next '%=' op needs to be unsigned
-            value -= range;
-            assert(value >= 0);
-        }
-        value %= range;
-        if (value < 0)  value += range;
-        value += min;
-        assert(min <= value && value <= max);
-        return value;
-    }
-
-    /** Does this coding support at least one negative value?
-        Includes codings that can do so via 32-bit wraparound.
-     */
-    boolean isSigned() {
-        return min < 0;
-    }
-    /** Does this coding code arrays by making successive differences? */
-    boolean isDelta() {
-        return del != 0;
-    }
-
-    public int B() { return B; }
-    public int H() { return H; }
-    public int L() { return L; }
-    public int S() { return S; }
-    public int del() { return del; }
-    public int min() { return min; }
-    public int max() { return max; }
-    public int umin() { return umin; }
-    public int umax() { return umax; }
-    public int byteMin(int b) { return byteMin[b-1]; }
-    public int byteMax(int b) { return byteMax[b-1]; }
-
-    public int compareTo(Coding that) {
-        int dkey = this.del - that.del;
-        if (dkey == 0)
-            dkey = this.B - that.B;
-        if (dkey == 0)
-            dkey = this.H - that.H;
-        if (dkey == 0)
-            dkey = this.S - that.S;
-        return dkey;
-    }
-
-    /** Heuristic measure of the difference between two codings. */
-    public int distanceFrom(Coding that) {
-        int diffdel = this.del - that.del;
-        if (diffdel < 0)  diffdel = -diffdel;
-        int diffS = this.S - that.S;
-        if (diffS < 0)  diffS = -diffS;
-        int diffB = this.B - that.B;
-        if (diffB < 0)  diffB = -diffB;
-        int diffHL;
-        if (this.H == that.H) {
-            diffHL = 0;
-        } else {
-            // Distance in log space of H (<=128) and L (<128).
-            int thisHL = this.getHL();
-            int thatHL = that.getHL();
-            // Double the accuracy of the log:
-            thisHL *= thisHL;
-            thatHL *= thatHL;
-            if (thisHL > thatHL)
-                diffHL = ceil_lg2(1+(thisHL-1)/thatHL);
-            else
-                diffHL = ceil_lg2(1+(thatHL-1)/thisHL);
-        }
-        int norm = 5*(diffdel + diffS + diffB) + diffHL;
-        assert(norm != 0 || this.compareTo(that) == 0);
-        return norm;
-    }
-    private int getHL() {
-        // Follow H in log space by the multiplicative inverse of L.
-        if (H <= 128)  return H;
-        if (L >= 1)    return 128*128/L;
-        return 128*256;
-    }
-
-    /** ceiling(log[2](x)): {1->0, 2->1, 3->2, 4->2, ...} */
-    static int ceil_lg2(int x) {
-        assert(x-1 >= 0);  // x in range (int.MIN_VALUE -> 32)
-        x -= 1;
-        int lg = 0;
-        while (x != 0) {
-            lg++;
-            x >>= 1;
-        }
-        return lg;
-    }
-
-    private static final byte[] byteBitWidths = new byte[0x100];
-    static {
-        for (int b = 0; b < byteBitWidths.length; b++) {
-            byteBitWidths[b] = (byte) ceil_lg2(b + 1);
-        }
-        for (int i = 10; i >= 0; i = (i << 1) - (i >> 3)) {
-            assert(bitWidth(i) == ceil_lg2(i + 1));
-        }
-    }
-
-    /** Number of significant bits in i, not counting sign bits.
-     *  For positive i, it is ceil_lg2(i + 1).
-     */
-    static int bitWidth(int i) {
-        if (i < 0)  i = ~i;  // change sign
-        int w = 0;
-        int lo = i;
-        if (lo < byteBitWidths.length)
-            return byteBitWidths[lo];
-        int hi;
-        hi = (lo >>> 16);
-        if (hi != 0) {
-            lo = hi;
-            w += 16;
-        }
-        hi = (lo >>> 8);
-        if (hi != 0) {
-            lo = hi;
-            w += 8;
-        }
-        w += byteBitWidths[lo];
-        //assert(w == ceil_lg2(i + 1));
-        return w;
-    }
-
-    /** Create an array of successive differences.
-     *  If min==max, accept any and all 32-bit overflow.
-     *  Otherwise, avoid 32-bit overflow, and reduce all differences
-     *  to a value in the given range, by adding or subtracting
-     *  multiples of the range cardinality (max-min+1).
-     *  Also, the values are assumed to be in the range [0..(max-min)].
-     */
-    static int[] makeDeltas(int[] values, int start, int end,
-                            int min, int max) {
-        assert(max >= min);
-        int count = end-start;
-        int[] deltas = new int[count];
-        int state = 0;
-        if (min == max) {
-            for (int i = 0; i < count; i++) {
-                int value = values[start+i];
-                deltas[i] = value - state;
-                state = value;
-            }
-        } else {
-            for (int i = 0; i < count; i++) {
-                int value = values[start+i];
-                assert(value >= 0 && value+min <= max);
-                int delta = value - state;
-                assert(delta == (long)value - (long)state); // no overflow
-                state = value;
-                // Reduce delta values to the required range.
-                delta = reduceToSignedRange(delta, min, max);
-                deltas[i] = delta;
-            }
-        }
-        return deltas;
-    }
-
-    boolean canRepresent(int minValue, int maxValue) {
-        assert(minValue <= maxValue);
-        if (del > 0) {
-            if (isSubrange()) {
-                // We will force the values to reduce to the right subrange.
-                return canRepresentUnsigned(maxValue)
-                    && canRepresentUnsigned(minValue);
-            } else {
-                // Huge range; delta values must assume full 32-bit range.
-                return isFullRange();
-            }
-        }
-        else
-            // final values must be representable
-            return canRepresentSigned(maxValue)
-                && canRepresentSigned(minValue);
-    }
-
-    boolean canRepresent(int[] values, int start, int end) {
-        int len = end-start;
-        if (len == 0)       return true;
-        if (isFullRange())  return true;
-        // Calculate max, min:
-        int lmax = values[start];
-        int lmin = lmax;
-        for (int i = 1; i < len; i++) {
-            int value = values[start+i];
-            if (lmax < value)  lmax = value;
-            if (lmin > value)  lmin = value;
-        }
-        return canRepresent(lmin, lmax);
-    }
-
-    public double getBitLength(int value) {  // implements BitMetric
-        return (double) getLength(value) * 8;
-    }
-
-    /** How many bytes are in the coding of this value?
-     *  Returns Integer.MAX_VALUE if the value has no coding.
-     *  The coding must not be a delta coding, since there is no
-     *  definite size for a single value apart from its context.
-     */
-    public int getLength(int value) {
-        if (isDelta() && isSubrange()) {
-            if (!canRepresentUnsigned(value))
-                return Integer.MAX_VALUE;
-            value = reduceToSignedRange(value);
-        }
-        if (value >= 0) {
-            for (int n = 0; n < B; n++) {
-                if (value <= byteMax[n])  return n+1;
-            }
-        } else {
-            for (int n = 0; n < B; n++) {
-                if (value >= byteMin[n])  return n+1;
-            }
-        }
-        return Integer.MAX_VALUE;
-    }
-
-    public int getLength(int[] values, int start, int end) {
-        int len = end-start;
-        if (B == 1)  return len;
-        if (L == 0)  return len * B;
-        if (isDelta()) {
-            int[] deltas;
-            if (!isSubrange())
-                deltas = makeDeltas(values, start, end, 0, 0);
-            else
-                deltas = makeDeltas(values, start, end, min, max);
-            //return Coding.of(B, H, S).getLength(deltas, 0, len);
-            values = deltas;
-            start = 0;
-        }
-        int sum = len;  // at least 1 byte per
-        // add extra bytes for extra-long values
-        for (int n = 1; n <= B; n++) {
-            // what is the coding interval [min..max] for n bytes?
-            int lmax = byteMax[n-1];
-            int lmin = byteMin[n-1];
-            int longer = 0;  // count of guys longer than n bytes
-            for (int i = 0; i < len; i++) {
-                int value = values[start+i];
-                if (value >= 0) {
-                    if (value > lmax)  longer++;
-                } else {
-                    if (value < lmin)  longer++;
-                }
-            }
-            if (longer == 0)  break;  // no more passes needed
-            if (n == B)  return Integer.MAX_VALUE;  // cannot represent!
-            sum += longer;
-        }
-        return sum;
-    }
-
-    public byte[] getMetaCoding(Coding dflt) {
-        if (dflt == this)  return new byte[]{ (byte) _meta_default };
-        int canonicalIndex = BandStructure.indexOf(this);
-        if (canonicalIndex > 0)
-            return new byte[]{ (byte) canonicalIndex };
-        return new byte[]{
-            (byte)_meta_arb,
-            (byte)(del + 2*S + 8*(B-1)),
-            (byte)(H-1)
-        };
-    }
-    public static int parseMetaCoding(byte[] bytes, int pos, Coding dflt, CodingMethod res[]) {
-        int op = bytes[pos++] & 0xFF;
-        if (_meta_canon_min <= op && op <= _meta_canon_max) {
-            Coding c = BandStructure.codingForIndex(op);
-            assert(c != null);
-            res[0] = c;
-            return pos;
-        }
-        if (op == _meta_arb) {
-            int dsb = bytes[pos++] & 0xFF;
-            int H_1 = bytes[pos++] & 0xFF;
-            int del = dsb % 2;
-            int S = (dsb / 2) % 4;
-            int B = (dsb / 8)+1;
-            int H = H_1+1;
-            if (!((1 <= B && B <= B_MAX) &&
-                  (0 <= S && S <= S_MAX) &&
-                  (1 <= H && H <= H_MAX) &&
-                  (0 <= del && del <= 1))
-                || (B == 1 && H != 256)
-                || (B == 5 && H == 256)) {
-                throw new RuntimeException("Bad arb. coding: ("+B+","+H+","+S+","+del);
-            }
-            res[0] = Coding.of(B, H, S, del);
-            return pos;
-        }
-        return pos-1;  // backup
-    }
-
-
-    public String keyString() {
-        return "("+B+","+H+","+S+","+del+")";
-    }
-
-    public String toString() {
-        String str = "Coding"+keyString();
-        // If -ea, print out more informative strings!
-        //assert((str = stringForDebug()) != null);
-        return str;
-    }
-
-    static boolean verboseStringForDebug = false;
-    String stringForDebug() {
-        String minS = (min == Integer.MIN_VALUE ? "min" : ""+min);
-        String maxS = (max == Integer.MAX_VALUE ? "max" : ""+max);
-        String str = keyString()+" L="+L+" r=["+minS+","+maxS+"]";
-        if (isSubrange())
-            str += " subrange";
-        else if (!isFullRange())
-            str += " MIDRANGE";
-        if (verboseStringForDebug) {
-            str += " {";
-            int prev_range = 0;
-            for (int n = 1; n <= B; n++) {
-                int range_n = saturate32((long)byteMax[n-1] - byteMin[n-1] + 1);
-                assert(range_n == saturate32(codeRangeLong(B, H, n)));
-                range_n -= prev_range;
-                prev_range = range_n;
-                String rngS = (range_n == Integer.MAX_VALUE ? "max" : ""+range_n);
-                str += " #"+n+"="+rngS;
-            }
-            str += " }";
-        }
-        return str;
-    }
-}
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/CodingChooser.java	Mon Dec 09 15:28:46 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1489 +0,0 @@
-/*
- * Copyright (c) 2002, 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 java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Random;
-import java.util.Set;
-import java.util.zip.Deflater;
-import java.util.zip.DeflaterOutputStream;
-import static com.sun.java.util.jar.pack.Constants.*;
-/**
- * Heuristic chooser of basic encodings.
- * Runs "zip" to measure the apparent information content after coding.
- * @author John Rose
- */
-class CodingChooser {
-    int verbose;
-    int effort;
-    boolean optUseHistogram = true;
-    boolean optUsePopulationCoding = true;
-    boolean optUseAdaptiveCoding = true;
-    boolean disablePopCoding;
-    boolean disableRunCoding;
-    boolean topLevel = true;
-
-    // Derived from effort; >1 (<1) means try more (less) experiments
-    // when looking to beat a best score.
-    double fuzz;
-
-    Coding[] allCodingChoices;
-    Choice[] choices;
-    ByteArrayOutputStream context;
-    CodingChooser popHelper;
-    CodingChooser runHelper;
-
-    Random stress;  // If not null, stress mode oracle.
-
-    // Element in sorted set of coding choices:
-    static
-    class Choice {
-        final Coding coding;
-        final int index;       // index in choices
-        final int[] distance;  // cache of distance
-        Choice(Coding coding, int index, int[] distance) {
-            this.coding   = coding;
-            this.index    = index;
-            this.distance = distance;
-        }
-        // These variables are reset and reused:
-        int searchOrder; // order in which it is checked
-        int minDistance; // min distance from already-checked choices
-        int zipSize;     // size of encoding in sample, zipped output
-        int byteSize;    // size of encoding in sample (debug only)
-        int histSize;    // size of encoding, according to histogram
-
-        void reset() {
-            searchOrder = Integer.MAX_VALUE;
-            minDistance = Integer.MAX_VALUE;
-            zipSize = byteSize = histSize = -1;
-        }
-
-        boolean isExtra() {
-            return index < 0;
-        }
-
-        public String toString() {
-            return stringForDebug();
-        }
-
-        private String stringForDebug() {
-            String s = "";
-            if (searchOrder < Integer.MAX_VALUE)
-                s += " so: "+searchOrder;
-            if (minDistance < Integer.MAX_VALUE)
-                s += " md: "+minDistance;
-            if (zipSize > 0)
-                s += " zs: "+zipSize;
-            if (byteSize > 0)
-                s += " bs: "+byteSize;
-            if (histSize > 0)
-                s += " hs: "+histSize;
-            return "Choice["+index+"] "+s+" "+coding;
-        }
-    }
-
-    CodingChooser(int effort, Coding[] allCodingChoices) {
-        PropMap p200 = Utils.currentPropMap();
-        if (p200 != null) {
-            this.verbose
-                = Math.max(p200.getInteger(Utils.DEBUG_VERBOSE),
-                           p200.getInteger(Utils.COM_PREFIX+"verbose.coding"));
-            this.optUseHistogram
-                = !p200.getBoolean(Utils.COM_PREFIX+"no.histogram");
-            this.optUsePopulationCoding
-                = !p200.getBoolean(Utils.COM_PREFIX+"no.population.coding");
-            this.optUseAdaptiveCoding
-                = !p200.getBoolean(Utils.COM_PREFIX+"no.adaptive.coding");
-            int lstress
-                = p200.getInteger(Utils.COM_PREFIX+"stress.coding");
-            if (lstress != 0)
-                this.stress = new Random(lstress);
-        }
-
-        this.effort = effort;
-        // The following line "makes sense" but is too much
-        // work for a simple heuristic.
-        //if (effort > 5)  zipDef.setLevel(effort);
-
-        this.allCodingChoices = allCodingChoices;
-
-        // If effort = 9, look carefully at any solution
-        // whose initial metrics are within 1% of the best
-        // so far.  If effort = 1, look carefully only at
-        // solutions whose initial metrics promise a 1% win.
-        this.fuzz = 1 + (0.0025 * (effort-MID_EFFORT));
-
-        int nc = 0;
-        for (int i = 0; i < allCodingChoices.length; i++) {
-            if (allCodingChoices[i] == null)  continue;
-            nc++;
-        }
-        choices = new Choice[nc];
-        nc = 0;
-        for (int i = 0; i < allCodingChoices.length; i++) {
-            if (allCodingChoices[i] == null)  continue;
-            int[] distance = new int[choices.length];
-            choices[nc++] = new Choice(allCodingChoices[i], i, distance);
-        }
-        for (int i = 0; i < choices.length; i++) {
-            Coding ci = choices[i].coding;
-            assert(ci.distanceFrom(ci) == 0);
-            for (int j = 0; j < i; j++) {
-                Coding cj = choices[j].coding;
-                int dij = ci.distanceFrom(cj);
-                assert(dij > 0);
-                assert(dij == cj.distanceFrom(ci));
-                choices[i].distance[j] = dij;
-                choices[j].distance[i] = dij;
-            }
-        }
-    }
-
-    Choice makeExtraChoice(Coding coding) {
-        int[] distance = new int[choices.length];
-        for (int i = 0; i < distance.length; i++) {
-            Coding ci = choices[i].coding;
-            int dij = coding.distanceFrom(ci);
-            assert(dij > 0);
-            assert(dij == ci.distanceFrom(coding));
-            distance[i] = dij;
-        }
-        Choice c = new Choice(coding, -1, distance);
-        c.reset();
-        return c;
-    }
-
-    ByteArrayOutputStream getContext() {
-        if (context == null)
-            context = new ByteArrayOutputStream(1 << 16);
-        return context;
-    }
-
-    // These variables are reset and reused:
-    private int[] values;
-    private int start, end;  // slice of values
-    private int[] deltas;
-    private int min, max;
-    private Histogram vHist;
-    private Histogram dHist;
-    private int searchOrder;
-    private Choice regularChoice;
-    private Choice bestChoice;
-    private CodingMethod bestMethod;
-    private int bestByteSize;
-    private int bestZipSize;
-    private int targetSize;   // fuzzed target byte size
-
-    private void reset(int[] values, int start, int end) {
-        this.values = values;
-        this.start = start;
-        this.end = end;
-        this.deltas = null;
-        this.min = Integer.MAX_VALUE;
-        this.max = Integer.MIN_VALUE;
-        this.vHist = null;
-        this.dHist = null;
-        this.searchOrder = 0;
-        this.regularChoice = null;
-        this.bestChoice = null;
-        this.bestMethod = null;
-        this.bestZipSize = Integer.MAX_VALUE;
-        this.bestByteSize = Integer.MAX_VALUE;
-        this.targetSize = Integer.MAX_VALUE;
-    }
-
-    public static final int MIN_EFFORT = 1;
-    public static final int MID_EFFORT = 5;
-    public static final int MAX_EFFORT = 9;
-
-    public static final int POP_EFFORT = MID_EFFORT-1;
-    public static final int RUN_EFFORT = MID_EFFORT-2;
-
-    public static final int BYTE_SIZE = 0;
-    public static final int ZIP_SIZE = 1;
-
-    CodingMethod choose(int[] values, int start, int end, Coding regular, int[] sizes) {
-        // Save the value array
-        reset(values, start, end);
-
-        if (effort <= MIN_EFFORT || start >= end) {
-            if (sizes != null) {
-                int[] computed = computeSizePrivate(regular);
-                sizes[BYTE_SIZE] = computed[BYTE_SIZE];
-                sizes[ZIP_SIZE]  = computed[ZIP_SIZE];
-            }
-            return regular;
-        }
-
-        if (optUseHistogram) {
-            getValueHistogram();
-            getDeltaHistogram();
-        }
-
-        for (int i = start; i < end; i++) {
-            int val = values[i];
-            if (min > val)  min = val;
-            if (max < val)  max = val;
-        }
-
-        // Find all the preset choices that might be worth looking at:
-        int numChoices = markUsableChoices(regular);
-
-        if (stress != null) {
-            // Make a random choice.
-            int rand = stress.nextInt(numChoices*2 + 4);
-            CodingMethod coding = null;
-            for (int i = 0; i < choices.length; i++) {
-                Choice c = choices[i];
-                if (c.searchOrder >= 0 && rand-- == 0) {
-                    coding = c.coding;
-                    break;
-                }
-            }
-            if (coding == null) {
-                if ((rand & 7) != 0) {
-                    coding = regular;
-                } else {
-                    // Pick a totally random coding 6% of the time.
-                    coding = stressCoding(min, max);
-                }
-            }
-            if (!disablePopCoding
-                && optUsePopulationCoding
-                && effort >= POP_EFFORT) {
-                coding = stressPopCoding(coding);
-            }
-            if (!disableRunCoding
-                && optUseAdaptiveCoding
-                && effort >= RUN_EFFORT) {
-                coding = stressAdaptiveCoding(coding);
-            }
-            return coding;
-        }
-
-        double searchScale = 1.0;
-        for (int x = effort; x < MAX_EFFORT; x++) {
-            searchScale /= 1.414;  // every 2 effort points doubles work
-        }
-        int searchOrderLimit = (int)Math.ceil( numChoices * searchScale );
-
-        // Start by evaluating the "regular" choice.
-        bestChoice = regularChoice;
-        evaluate(regularChoice);
-        int maxd = updateDistances(regularChoice);
-
-        // save these first-cut numbers for later
-        int zipSize1 = bestZipSize;
-        int byteSize1 = bestByteSize;
-
-        if (regularChoice.coding == regular && topLevel) {
-            // Give credit for being the default; no band header is needed.
-            // Rather than increasing every other size value by the band
-            // header amount, we decrement this one metric, to give it an edge.
-            // Decreasing zipSize by a byte length is conservatively correct,
-            // especially considering that the escape byte is not likely to
-            // zip well with other bytes in the band.
-            int X = BandStructure.encodeEscapeValue(_meta_canon_max, regular);
-            if (regular.canRepresentSigned(X)) {
-                int Xlen = regular.getLength(X);  // band coding header
-                //regularChoice.histSize -= Xlen; // keep exact byteSize
-                //regularChoice.byteSize -= Xlen; // keep exact byteSize
-                regularChoice.zipSize -= Xlen;
-                bestByteSize = regularChoice.byteSize;
-                bestZipSize = regularChoice.zipSize;
-            }
-        }
-
-        int dscale = 1;
-        // Continually select a new choice to evaluate.
-        while (searchOrder < searchOrderLimit) {
-            Choice nextChoice;
-            if (dscale > maxd)  dscale = 1;  // cycle dscale values!
-            int dhi = maxd / dscale;
-            int dlo = maxd / (dscale *= 2) + 1;
-            nextChoice = findChoiceNear(bestChoice, dhi, dlo);
-            if (nextChoice == null)  continue;
-            assert(nextChoice.coding.canRepresent(min, max));
-            evaluate(nextChoice);
-            int nextMaxd = updateDistances(nextChoice);
-            if (nextChoice == bestChoice) {
-                maxd = nextMaxd;
-                if (verbose > 5)  Utils.log.info("maxd = "+maxd);
-            }
-        }
-
-        // Record best "plain coding" choice.
-        Coding plainBest = bestChoice.coding;
-        assert(plainBest == bestMethod);
-
-        if (verbose > 2) {
-            Utils.log.info("chooser: plain result="+bestChoice+" after "+bestChoice.searchOrder+" rounds, "+(regularChoice.zipSize-bestZipSize)+" fewer bytes than regular "+regular);
-        }
-        bestChoice = null;
-
-        if (!disablePopCoding
-            && optUsePopulationCoding
-            && effort >= POP_EFFORT
-            && bestMethod instanceof Coding) {
-            tryPopulationCoding(plainBest);
-        }
-
-        if (!disableRunCoding
-            && optUseAdaptiveCoding
-            && effort >= RUN_EFFORT
-            && bestMethod instanceof Coding) {
-            tryAdaptiveCoding(plainBest);
-        }
-
-        // Pass back the requested information:
-        if (sizes != null) {
-            sizes[BYTE_SIZE] = bestByteSize;
-            sizes[ZIP_SIZE]  = bestZipSize;
-        }
-        if (verbose > 1) {
-            Utils.log.info("chooser: result="+bestMethod+" "+
-                             (zipSize1-bestZipSize)+
-                             " fewer bytes than regular "+regular+
-                             "; win="+pct(zipSize1-bestZipSize, zipSize1));
-        }
-        CodingMethod lbestMethod = this.bestMethod;
-        reset(null, 0, 0);  // for GC
-        return lbestMethod;
-    }
-    CodingMethod choose(int[] values, int start, int end, Coding regular) {
-        return choose(values, start, end, regular, null);
-    }
-    CodingMethod choose(int[] values, Coding regular, int[] sizes) {
-        return choose(values, 0, values.length, regular, sizes);
-    }
-    CodingMethod choose(int[] values, Coding regular) {
-        return choose(values, 0, values.length, regular, null);
-    }
-
-    private int markUsableChoices(Coding regular) {
-        int numChoices = 0;
-        for (int i = 0; i < choices.length; i++) {
-            Choice c = choices[i];
-            c.reset();
-            if (!c.coding.canRepresent(min, max)) {
-                // Mark as already visited:
-                c.searchOrder = -1;
-                if (verbose > 1 && c.coding == regular) {
-                    Utils.log.info("regular coding cannot represent ["+min+".."+max+"]: "+regular);
-                }
-                continue;
-            }
-            if (c.coding == regular)
-                regularChoice = c;
-            numChoices++;
-        }
-        if (regularChoice == null && regular.canRepresent(min, max)) {
-            regularChoice = makeExtraChoice(regular);
-            if (verbose > 1) {
-                Utils.log.info("*** regular choice is extra: "+regularChoice.coding);
-            }
-        }
-        if (regularChoice == null) {
-            for (int i = 0; i < choices.length; i++) {
-                Choice c = choices[i];
-                if (c.searchOrder != -1) {
-                    regularChoice = c;  // arbitrary pick
-                    break;
-                }
-            }
-            if (verbose > 1) {
-                Utils.log.info("*** regular choice does not apply "+regular);
-                Utils.log.info("    using instead "+regularChoice.coding);
-            }
-        }
-        if (verbose > 2) {
-            Utils.log.info("chooser: #choices="+numChoices+" ["+min+".."+max+"]");
-            if (verbose > 4) {
-                for (int i = 0; i < choices.length; i++) {
-                    Choice c = choices[i];
-                    if (c.searchOrder >= 0)
-                        Utils.log.info("  "+c);
-                }
-            }
-        }
-        return numChoices;
-    }
-
-    // Find an arbitrary choice at least dlo away from a previously
-    // evaluated choices, and at most dhi.  Try also to regulate its
-    // min distance to all previously evaluated choices, in this range.
-    private Choice findChoiceNear(Choice near, int dhi, int dlo) {
-        if (verbose > 5)
-            Utils.log.info("findChoice "+dhi+".."+dlo+" near: "+near);
-        int[] distance = near.distance;
-        Choice found = null;
-        for (int i = 0; i < choices.length; i++) {
-            Choice c = choices[i];
-            if (c.searchOrder < searchOrder)
-                continue;  // already searched
-            // Distance from "near" guy must be in bounds:
-            if (distance[i] >= dlo && distance[i] <= dhi) {
-                // Try also to keep min-distance from other guys in bounds:
-                if (c.minDistance >= dlo && c.minDistance <= dhi) {
-                    if (verbose > 5)
-                        Utils.log.info("findChoice => good "+c);
-                    return c;
-                }
-                found = c;
-            }
-        }
-        if (verbose > 5)
-            Utils.log.info("findChoice => found "+found);
-        return found;
-    }
-
-    private void evaluate(Choice c) {
-        assert(c.searchOrder == Integer.MAX_VALUE);
-        c.searchOrder = searchOrder++;
-        boolean mustComputeSize;
-        if (c == bestChoice || c.isExtra()) {
-            mustComputeSize = true;
-        } else if (optUseHistogram) {
-            Histogram hist = getHistogram(c.coding.isDelta());
-            c.histSize = (int)Math.ceil(hist.getBitLength(c.coding) / 8);
-            c.byteSize = c.histSize;
-            mustComputeSize = (c.byteSize <= targetSize);
-        } else {
-            mustComputeSize = true;
-        }
-        if (mustComputeSize) {
-            int[] sizes = computeSizePrivate(c.coding);
-            c.byteSize = sizes[BYTE_SIZE];
-            c.zipSize  = sizes[ZIP_SIZE];
-            if (noteSizes(c.coding, c.byteSize, c.zipSize))
-                bestChoice = c;
-        }
-        if (c.histSize >= 0) {
-            assert(c.byteSize == c.histSize);  // models should agree
-        }
-        if (verbose > 4) {
-            Utils.log.info("evaluated "+c);
-        }
-    }
-
-    private boolean noteSizes(CodingMethod c, int byteSize, int zipSize) {
-        assert(zipSize > 0 && byteSize > 0);
-        boolean better = (zipSize < bestZipSize);
-        if (verbose > 3)
-            Utils.log.info("computed size "+c+" "+byteSize+"/zs="+zipSize+
-                             ((better && bestMethod != null)?
-                              (" better by "+
-                               pct(bestZipSize - zipSize, zipSize)): ""));
-        if (better) {
-            bestMethod = c;
-            bestZipSize = zipSize;
-            bestByteSize = byteSize;
-            targetSize = (int)(byteSize * fuzz);
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-
-    private int updateDistances(Choice c) {
-        // update all minDistance values in still unevaluated choices
-        int[] distance = c.distance;
-        int maxd = 0;  // how far is c from everybody else?
-        for (int i = 0; i < choices.length; i++) {
-            Choice c2 = choices[i];
-            if (c2.searchOrder < searchOrder)
-                continue;
-            int d = distance[i];
-            if (verbose > 5)
-                Utils.log.info("evaluate dist "+d+" to "+c2);
-            int mind = c2.minDistance;
-            if (mind > d)
-                c2.minDistance = mind = d;
-            if (maxd < d)
-                maxd = d;
-        }
-        // Now maxd has the distance of the farthest outlier
-        // from all evaluated choices.
-        if (verbose > 5)
-            Utils.log.info("evaluate maxd => "+maxd);
-        return maxd;
-    }
-
-    // Compute the coded size of a sequence of values.
-    // The first int is the size in uncompressed bytes.
-    // The second is an estimate of the compressed size of these bytes.
-    public void computeSize(CodingMethod c, int[] values, int start, int end, int[] sizes) {
-        if (end <= start) {
-            sizes[BYTE_SIZE] = sizes[ZIP_SIZE] = 0;
-            return;
-        }
-        try {
-            resetData();
-            c.writeArrayTo(byteSizer, values, start, end);
-            sizes[BYTE_SIZE] = getByteSize();
-            sizes[ZIP_SIZE] = getZipSize();
-        } catch (IOException ee) {
-            throw new RuntimeException(ee); // cannot happen
-        }
-    }
-    public void computeSize(CodingMethod c, int[] values, int[] sizes) {
-        computeSize(c, values, 0, values.length, sizes);
-    }
-    public int[] computeSize(CodingMethod c, int[] values, int start, int end) {
-        int[] sizes = { 0, 0 };
-        computeSize(c, values, start, end, sizes);
-        return sizes;
-    }
-    public int[] computeSize(CodingMethod c, int[] values) {
-        return computeSize(c, values, 0, values.length);
-    }
-    // This version uses the implicit local arguments
-    private int[] computeSizePrivate(CodingMethod c) {
-        int[] sizes = { 0, 0 };
-        computeSize(c, values, start, end, sizes);
-        return sizes;
-    }
-    public int computeByteSize(CodingMethod cm, int[] values, int start, int end) {
-        int len = end-start;
-        if (len < 0) {
-            return 0;
-        }
-        if (cm instanceof Coding) {
-            Coding c = (Coding) cm;
-            int size = c.getLength(values, start, end);
-            int size2;
-            assert(size == (size2=countBytesToSizer(cm, values, start, end)))
-                : (cm+" : "+size+" != "+size2);
-            return size;
-        }
-        return countBytesToSizer(cm, values, start, end);
-    }
-    private int countBytesToSizer(CodingMethod cm, int[] values, int start, int end) {
-        try {
-            byteOnlySizer.reset();
-            cm.writeArrayTo(byteOnlySizer, values, start, end);
-            return byteOnlySizer.getSize();
-        } catch (IOException ee) {
-            throw new RuntimeException(ee); // cannot happen
-        }
-    }
-
-    int[] getDeltas(int min, int max) {
-        if ((min|max) != 0)
-            return Coding.makeDeltas(values, start, end, min, max);
-        if (deltas == null) {
-            deltas = Coding.makeDeltas(values, start, end, 0, 0);
-        }
-        return deltas;
-    }
-    Histogram getValueHistogram() {
-        if (vHist == null) {
-            vHist = new Histogram(values, start, end);
-            if (verbose > 3) {
-                vHist.print("vHist", System.out);
-            } else if (verbose > 1) {
-                vHist.print("vHist", null, System.out);
-            }
-        }
-        return vHist;
-    }
-    Histogram getDeltaHistogram() {
-        if (dHist == null) {
-            dHist = new Histogram(getDeltas(0, 0));
-            if (verbose > 3) {
-                dHist.print("dHist", System.out);
-            } else if (verbose > 1) {
-                dHist.print("dHist", null, System.out);
-            }
-        }
-        return dHist;
-    }
-    Histogram getHistogram(boolean isDelta) {
-        return isDelta ? getDeltaHistogram(): getValueHistogram();
-    }
-
-    private void tryPopulationCoding(Coding plainCoding) {
-        // assert(plainCoding.canRepresent(min, max));
-        Histogram hist = getValueHistogram();
-        // Start with "reasonable" default codings.
-        final int approxL = 64;
-        Coding favoredCoding = plainCoding.getValueCoding();
-        Coding tokenCoding = BandStructure.UNSIGNED5.setL(approxL);
-        Coding unfavoredCoding = plainCoding.getValueCoding();
-        // There's going to be a band header.  Estimate conservatively large.
-        final int BAND_HEADER = 4;
-        // Keep a running model of the predicted sizes of the F/T/U sequences.
-        int currentFSize;
-        int currentTSize;
-        int currentUSize;
-        // Start by assuming a degenerate favored-value length of 0,
-        // which looks like a bunch of zero tokens followed by the
-        // original sequence.
-        // The {F} list ends with a repeated F value; find worst case:
-        currentFSize =
-            BAND_HEADER + Math.max(favoredCoding.getLength(min),
-                                   favoredCoding.getLength(max));
-        // The {T} list starts out a bunch of zeros, each of length 1.
-        final int ZERO_LEN = tokenCoding.getLength(0);
-        currentTSize = ZERO_LEN * (end-start);
-        // The {U} list starts out a copy of the plainCoding:
-        currentUSize = (int) Math.ceil(hist.getBitLength(unfavoredCoding) / 8);
-
-        int bestPopSize = (currentFSize + currentTSize + currentUSize);
-        int bestPopFVC  = 0;
-
-        // Record all the values, in decreasing order of favor.
-        int[] allFavoredValues = new int[1+hist.getTotalLength()];
-        //int[] allPopSizes    = new int[1+hist.getTotalLength()];
-
-        // What sizes are "interesting"?
-        int targetLowFVC = -1;
-        int targetHighFVC = -1;
-
-        // For each length, adjust the currentXSize model, and look for a win.
-        int[][] matrix = hist.getMatrix();
-        int mrow = -1;
-        int mcol = 1;
-        int mrowFreq = 0;
-        for (int fvcount = 1; fvcount <= hist.getTotalLength(); fvcount++) {
-            // The {F} list gets an additional member.
-            // Take it from the end of the current matrix row.
-            // (It's the end, so that we get larger favored values first.)
-            if (mcol == 1) {
-                mrow += 1;
-                mrowFreq = matrix[mrow][0];
-                mcol = matrix[mrow].length;
-            }
-            int thisValue = matrix[mrow][--mcol];
-            allFavoredValues[fvcount] = thisValue;
-            int thisVLen = favoredCoding.getLength(thisValue);
-            currentFSize += thisVLen;
-            // The token list replaces occurrences of zero with a new token:
-            int thisVCount = mrowFreq;
-            int thisToken = fvcount;
-            currentTSize += (tokenCoding.getLength(thisToken)
-                             - ZERO_LEN) * thisVCount;
-            // The unfavored list loses occurrences of the newly favored value.
-            // (This is the whole point of the exercise!)
-            currentUSize -= thisVLen * thisVCount;
-            int currentSize = (currentFSize + currentTSize + currentUSize);
-            //allPopSizes[fvcount] = currentSize;
-            if (bestPopSize > currentSize) {
-                if (currentSize <= targetSize) {
-                    targetHighFVC = fvcount;
-                    if (targetLowFVC < 0)
-                        targetLowFVC = fvcount;
-                    if (verbose > 4)
-                        Utils.log.info("better pop-size at fvc="+fvcount+
-                                         " by "+pct(bestPopSize-currentSize,
-                                                    bestPopSize));
-                }
-                bestPopSize = currentSize;
-                bestPopFVC = fvcount;
-            }
-        }
-        if (targetLowFVC < 0) {
-            if (verbose > 1) {
-                // Complete loss.
-                if (verbose > 1)
-                    Utils.log.info("no good pop-size; best was "+
-                                     bestPopSize+" at "+bestPopFVC+
-                                     " worse by "+
-                                     pct(bestPopSize-bestByteSize,
-                                         bestByteSize));
-            }
-            return;
-        }
-        if (verbose > 1)
-            Utils.log.info("initial best pop-size at fvc="+bestPopFVC+
-                             " in ["+targetLowFVC+".."+targetHighFVC+"]"+
-                             " by "+pct(bestByteSize-bestPopSize,
-                                        bestByteSize));
-        int oldZipSize = bestZipSize;
-        // Now close onto a specific coding, testing more rigorously
-        // with the zipSize metric.
-        // Questions to decide:
-        //   1. How many favored values?
-        //   2. What token coding (TC)?
-        //   3. Sort favored values by value within length brackets?
-        //   4. What favored coding?
-        //   5. What unfavored coding?
-        // Steps 1/2/3 are interdependent, and may be iterated.
-        // Steps 4 and 5 may be decided independently afterward.
-        int[] LValuesCoded = PopulationCoding.LValuesCoded;
-        List<Coding> bestFits = new ArrayList<>();
-        List<Coding> fullFits = new ArrayList<>();
-        List<Coding> longFits = new ArrayList<>();
-        final int PACK_TO_MAX_S = 1;
-        if (bestPopFVC <= 255) {
-            bestFits.add(BandStructure.BYTE1);
-        } else {
-            int bestB = Coding.B_MAX;
-            boolean doFullAlso = (effort > POP_EFFORT);
-            if (doFullAlso)
-                fullFits.add(BandStructure.BYTE1.setS(PACK_TO_MAX_S));
-            for (int i = LValuesCoded.length-1; i >= 1; i--) {
-                int L = LValuesCoded[i];
-                Coding c0 = PopulationCoding.fitTokenCoding(targetLowFVC,  L);
-                Coding c1 = PopulationCoding.fitTokenCoding(bestPopFVC,    L);
-                Coding c3 = PopulationCoding.fitTokenCoding(targetHighFVC, L);
-                if (c1 != null) {
-                    if (!bestFits.contains(c1))
-                        bestFits.add(c1);
-                    if (bestB > c1.B())
-                        bestB = c1.B();
-                }
-                if (doFullAlso) {
-                    if (c3 == null)  c3 = c1;
-                    for (int B = c0.B(); B <= c3.B(); B++) {
-                        if (B == c1.B())  continue;
-                        if (B == 1)  continue;
-                        Coding c2 = c3.setB(B).setS(PACK_TO_MAX_S);
-                        if (!fullFits.contains(c2))
-                            fullFits.add(c2);
-                    }
-                }
-            }
-            // interleave all B greater than bestB with best and full fits
-            for (Iterator<Coding> i = bestFits.iterator(); i.hasNext(); ) {
-                Coding c = i.next();
-                if (c.B() > bestB) {
-                    i.remove();
-                    longFits.add(0, c);
-                }
-            }
-        }
-        List<Coding> allFits = new ArrayList<>();
-        for (Iterator<Coding> i = bestFits.iterator(),
-                      j = fullFits.iterator(),
-                      k = longFits.iterator();
-             i.hasNext() || j.hasNext() || k.hasNext(); ) {
-            if (i.hasNext())  allFits.add(i.next());
-            if (j.hasNext())  allFits.add(j.next());
-            if (k.hasNext())  allFits.add(k.next());
-        }
-        bestFits.clear();
-        fullFits.clear();
-        longFits.clear();
-        int maxFits = allFits.size();
-        if (effort == POP_EFFORT)
-            maxFits = 2;
-        else if (maxFits > 4) {
-            maxFits -= 4;
-            maxFits = (maxFits * (effort-POP_EFFORT)
-                       ) / (MAX_EFFORT-POP_EFFORT);
-            maxFits += 4;
-        }
-        if (allFits.size() > maxFits) {
-            if (verbose > 4)
-                Utils.log.info("allFits before clip: "+allFits);
-            allFits.subList(maxFits, allFits.size()).clear();
-        }
-        if (verbose > 3)
-            Utils.log.info("allFits: "+allFits);
-        for (Coding tc : allFits) {
-            boolean packToMax = false;
-            if (tc.S() == PACK_TO_MAX_S) {
-                // Kludge:  setS(PACK_TO_MAX_S) means packToMax here.
-                packToMax = true;
-                tc = tc.setS(0);
-            }
-            int fVlen;
-            if (!packToMax) {
-                fVlen = bestPopFVC;
-                assert(tc.umax() >= fVlen);
-                assert(tc.B() == 1 || tc.setB(tc.B()-1).umax() < fVlen);
-            } else {
-                fVlen = Math.min(tc.umax(), targetHighFVC);
-                if (fVlen < targetLowFVC)
-                    continue;
-                if (fVlen == bestPopFVC)
-                    continue;  // redundant test
-            }
-            PopulationCoding pop = new PopulationCoding();
-            pop.setHistogram(hist);
-            pop.setL(tc.L());
-            pop.setFavoredValues(allFavoredValues, fVlen);
-            assert(pop.tokenCoding == tc);  // predict correctly
-            pop.resortFavoredValues();
-            int[] tcsizes =
-                computePopSizePrivate(pop,
-                                      favoredCoding, unfavoredCoding);
-            noteSizes(pop, tcsizes[BYTE_SIZE], BAND_HEADER+tcsizes[ZIP_SIZE]);
-        }
-        if (verbose > 3) {
-            Utils.log.info("measured best pop, size="+bestByteSize+
-                             "/zs="+bestZipSize+
-                             " better by "+
-                             pct(oldZipSize-bestZipSize, oldZipSize));
-            if (bestZipSize < oldZipSize) {
-                Utils.log.info(">>> POP WINS BY "+
-                                 (oldZipSize - bestZipSize));
-            }
-        }
-    }
-
-    private
-    int[] computePopSizePrivate(PopulationCoding pop,
-                                Coding favoredCoding,
-                                Coding unfavoredCoding) {
-        if (popHelper == null) {
-            popHelper = new CodingChooser(effort, allCodingChoices);
-            if (stress != null)
-                popHelper.addStressSeed(stress.nextInt());
-            popHelper.topLevel = false;
-            popHelper.verbose -= 1;
-            popHelper.disablePopCoding = true;
-            popHelper.disableRunCoding = this.disableRunCoding;
-            if (effort < MID_EFFORT)
-                // No nested run codings.
-                popHelper.disableRunCoding = true;
-        }
-        int fVlen = pop.fVlen;
-        if (verbose > 2) {
-            Utils.log.info("computePopSizePrivate fvlen="+fVlen+
-                             " tc="+pop.tokenCoding);
-            Utils.log.info("{ //BEGIN");
-        }
-
-        // Find good coding choices for the token and unfavored sequences.
-        int[] favoredValues = pop.fValues;
-        int[][] vals = pop.encodeValues(values, start, end);
-        int[] tokens = vals[0];
-        int[] unfavoredValues = vals[1];
-        if (verbose > 2)
-            Utils.log.info("-- refine on fv["+fVlen+"] fc="+favoredCoding);
-        pop.setFavoredCoding(popHelper.choose(favoredValues, 1, 1+fVlen, favoredCoding));
-        if (pop.tokenCoding instanceof Coding &&
-            (stress == null || stress.nextBoolean())) {
-            if (verbose > 2)
-                Utils.log.info("-- refine on tv["+tokens.length+"] tc="+pop.tokenCoding);
-            CodingMethod tc = popHelper.choose(tokens, (Coding) pop.tokenCoding);
-            if (tc != pop.tokenCoding) {
-                if (verbose > 2)
-                    Utils.log.info(">>> refined tc="+tc);
-                pop.setTokenCoding(tc);
-            }
-        }
-        if (unfavoredValues.length == 0)
-            pop.setUnfavoredCoding(null);
-        else {
-            if (verbose > 2)
-                Utils.log.info("-- refine on uv["+unfavoredValues.length+"] uc="+pop.unfavoredCoding);
-            pop.setUnfavoredCoding(popHelper.choose(unfavoredValues, unfavoredCoding));
-        }
-        if (verbose > 3) {
-            Utils.log.info("finish computePopSizePrivate fvlen="+fVlen+
-                             " fc="+pop.favoredCoding+
-                             " tc="+pop.tokenCoding+
-                             " uc="+pop.unfavoredCoding);
-            //pop.hist.print("pop-hist", null, System.out);
-            StringBuilder sb = new StringBuilder();
-            sb.append("fv = {");
-            for (int i = 1; i <= fVlen; i++) {
-                if ((i % 10) == 0)
-                    sb.append('\n');
-                sb.append(" ").append(favoredValues[i]);
-            }
-            sb.append('\n');
-            sb.append("}");
-            Utils.log.info(sb.toString());
-        }
-        if (verbose > 2) {
-            Utils.log.info("} //END");
-        }
-        if (stress != null) {
-            return null;  // do not bother with size computation
-        }
-        int[] sizes;
-        try {
-            resetData();
-            // Write the array of favored values.
-            pop.writeSequencesTo(byteSizer, tokens, unfavoredValues);
-            sizes = new int[] { getByteSize(), getZipSize() };
-        } catch (IOException ee) {
-            throw new RuntimeException(ee); // cannot happen
-        }
-        int[] checkSizes = null;
-        assert((checkSizes = computeSizePrivate(pop)) != null);
-        assert(checkSizes[BYTE_SIZE] == sizes[BYTE_SIZE])
-            : (checkSizes[BYTE_SIZE]+" != "+sizes[BYTE_SIZE]);
-        return sizes;
-    }
-
-    private void tryAdaptiveCoding(Coding plainCoding) {
-        int oldZipSize = bestZipSize;
-        // Scan the value sequence, determining whether an interesting
-        // run occupies too much space.  ("Too much" means, say 5% more
-        // than the average integer size of the band as a whole.)
-        // Try to find a better coding for those segments.
-        int   lstart  = this.start;
-        int   lend    = this.end;
-        int[] lvalues = this.values;
-        int len = lend-lstart;
-        if (plainCoding.isDelta()) {
-            lvalues = getDeltas(0,0); //%%% not quite right!
-            lstart = 0;
-            lend = lvalues.length;
-        }
-        int[] sizes = new int[len+1];
-        int fillp = 0;
-        int totalSize = 0;
-        for (int i = lstart; i < lend; i++) {
-            int val = lvalues[i];
-            sizes[fillp++] = totalSize;
-            int size = plainCoding.getLength(val);
-            assert(size < Integer.MAX_VALUE);
-            //System.out.println("len "+val+" = "+size);
-            totalSize += size;
-        }
-        sizes[fillp++] = totalSize;
-        assert(fillp == sizes.length);
-        double avgSize = (double)totalSize / len;
-        double sizeFuzz;
-        double sizeFuzz2;
-        double sizeFuzz3;
-        if (effort >= MID_EFFORT) {
-            if (effort > MID_EFFORT+1)
-                sizeFuzz = 1.001;
-            else
-                sizeFuzz = 1.003;
-        } else {
-            if (effort > RUN_EFFORT)
-                sizeFuzz = 1.01;
-            else
-                sizeFuzz = 1.03;
-        }
-        // for now:
-        sizeFuzz *= sizeFuzz; // double the thresh
-        sizeFuzz2 = (sizeFuzz*sizeFuzz);
-        sizeFuzz3 = (sizeFuzz*sizeFuzz*sizeFuzz);
-        // Find some mesh scales we like.
-        double[] dmeshes = new double[1 + (effort-RUN_EFFORT)];
-        double logLen = Math.log(len);
-        for (int i = 0; i < dmeshes.length; i++) {
-            dmeshes[i] = Math.exp(logLen*(i+1)/(dmeshes.length+1));
-        }
-        int[] meshes = new int[dmeshes.length];
-        int mfillp = 0;
-        for (int i = 0; i < dmeshes.length; i++) {
-            int m = (int)Math.round(dmeshes[i]);
-            m = AdaptiveCoding.getNextK(m-1);
-            if (m <= 0 || m >= len)  continue;
-            if (mfillp > 0 && m == meshes[mfillp-1])  continue;
-            meshes[mfillp++] = m;
-        }
-        meshes = BandStructure.realloc(meshes, mfillp);
-        // There's going to be a band header.  Estimate conservatively large.
-        final int BAND_HEADER = 4; // op, KB, A, B
-        // Threshold values for a "too big" mesh.
-        int[]    threshes = new int[meshes.length];
-        double[] fuzzes   = new double[meshes.length];
-        for (int i = 0; i < meshes.length; i++) {
-            int mesh = meshes[i];
-            double lfuzz;
-            if (mesh < 10)
-                lfuzz = sizeFuzz3;
-            else if (mesh < 100)
-                lfuzz = sizeFuzz2;
-            else
-                lfuzz = sizeFuzz;
-            fuzzes[i] = lfuzz;
-            threshes[i] = BAND_HEADER + (int)Math.ceil(mesh * avgSize * lfuzz);
-        }
-        if (verbose > 1) {
-            System.out.print("tryAdaptiveCoding ["+len+"]"+
-                             " avgS="+avgSize+" fuzz="+sizeFuzz+
-                             " meshes: {");
-            for (int i = 0; i < meshes.length; i++) {
-                System.out.print(" " + meshes[i] + "(" + threshes[i] + ")");
-            }
-            Utils.log.info(" }");
-        }
-        if (runHelper == null) {
-            runHelper = new CodingChooser(effort, allCodingChoices);
-            if (stress != null)
-                runHelper.addStressSeed(stress.nextInt());
-            runHelper.topLevel = false;
-            runHelper.verbose -= 1;
-            runHelper.disableRunCoding = true;
-            runHelper.disablePopCoding = this.disablePopCoding;
-            if (effort < MID_EFFORT)
-                // No nested pop codings.
-                runHelper.disablePopCoding = true;
-        }
-        for (int i = 0; i < len; i++) {
-            i = AdaptiveCoding.getNextK(i-1);
-            if (i > len)  i = len;
-            for (int j = meshes.length-1; j >= 0; j--) {
-                int mesh   = meshes[j];
-                int thresh = threshes[j];
-                if (i+mesh > len)  continue;
-                int size = sizes[i+mesh] - sizes[i];
-                if (size >= thresh) {
-                    // Found a size bulge.
-                    int bend  = i+mesh;
-                    int bsize = size;
-                    double bigSize = avgSize * fuzzes[j];
-                    while (bend < len && (bend-i) <= len/2) {
-                        int bend0 = bend;
-                        int bsize0 = bsize;
-                        bend += mesh;
-                        bend = i+AdaptiveCoding.getNextK(bend-i-1);
-                        if (bend < 0 || bend > len)
-                            bend = len;
-                        bsize = sizes[bend]-sizes[i];
-                        if (bsize < BAND_HEADER + (bend-i) * bigSize) {
-                            bsize = bsize0;
-                            bend = bend0;
-                            break;
-                        }
-                    }
-                    int nexti = bend;
-                    if (verbose > 2) {
-                        Utils.log.info("bulge at "+i+"["+(bend-i)+"] of "+
-                                         pct(bsize - avgSize*(bend-i),
-                                             avgSize*(bend-i)));
-                        Utils.log.info("{ //BEGIN");
-                    }
-                    CodingMethod begcm, midcm, endcm;
-                    midcm = runHelper.choose(this.values,
-                                             this.start+i,
-                                             this.start+bend,
-                                             plainCoding);
-                    if (midcm == plainCoding) {
-                        // No use working further.
-                        begcm = plainCoding;
-                        endcm = plainCoding;
-                    } else {
-                        begcm = runHelper.choose(this.values,
-                                                 this.start,
-                                                 this.start+i,
-                                                 plainCoding);
-                        endcm = runHelper.choose(this.values,
-                                                 this.start+bend,
-                                                 this.start+len,
-                                                 plainCoding);
-                    }
-                    if (verbose > 2)
-                        Utils.log.info("} //END");
-                    if (begcm == midcm && i > 0 &&
-                        AdaptiveCoding.isCodableLength(bend)) {
-                        i = 0;
-                    }
-                    if (midcm == endcm && bend < len) {
-                        bend = len;
-                    }
-                    if (begcm != plainCoding ||
-                        midcm != plainCoding ||
-                        endcm != plainCoding) {
-                        CodingMethod chain;
-                        int hlen = 0;
-                        if (bend == len) {
-                            chain = midcm;
-                        } else {
-                            chain = new AdaptiveCoding(bend-i, midcm, endcm);
-                            hlen += BAND_HEADER;
-                        }
-                        if (i > 0) {
-                            chain = new AdaptiveCoding(i, begcm, chain);
-                            hlen += BAND_HEADER;
-                        }
-                        int[] chainSize = computeSizePrivate(chain);
-                        noteSizes(chain,
-                                  chainSize[BYTE_SIZE],
-                                  chainSize[ZIP_SIZE]+hlen);
-                    }
-                    i = nexti;
-                    break;
-                }
-            }
-        }
-        if (verbose > 3) {
-            if (bestZipSize < oldZipSize) {
-                Utils.log.info(">>> RUN WINS BY "+
-                                 (oldZipSize - bestZipSize));
-            }
-        }
-    }
-
-    private static
-    String pct(double num, double den) {
-        return (Math.round((num / den)*10000)/100.0)+"%";
-    }
-
-    static
-    class Sizer extends OutputStream {
-        final OutputStream out;  // if non-null, copy output here also
-        Sizer(OutputStream out) {
-            this.out = out;
-        }
-        Sizer() {
-            this(null);
-        }
-        private int count;
-        public void write(int b) throws IOException {
-            count++;
-            if (out != null)  out.write(b);
-        }
-        public void write(byte b[], int off, int len) throws IOException {
-            count += len;
-            if (out != null)  out.write(b, off, len);
-        }
-        public void reset() {
-            count = 0;
-        }
-        public int getSize() { return count; }
-
-        public String toString() {
-            String str = super.toString();
-            // If -ea, print out more informative strings!
-            assert((str = stringForDebug()) != null);
-            return str;
-        }
-        String stringForDebug() {
-            return "<Sizer "+getSize()+">";
-        }
-    }
-
-    private Sizer zipSizer  = new Sizer();
-    private Deflater zipDef = new Deflater();
-    private DeflaterOutputStream zipOut = new DeflaterOutputStream(zipSizer, zipDef);
-    private Sizer byteSizer = new Sizer(zipOut);
-    private Sizer byteOnlySizer = new Sizer();
-
-    private void resetData() {
-        flushData();
-        zipDef.reset();
-        if (context != null) {
-            // Prepend given salt to the test output.
-            try {
-                context.writeTo(byteSizer);
-            } catch (IOException ee) {
-                throw new RuntimeException(ee); // cannot happen
-            }
-        }
-        zipSizer.reset();
-        byteSizer.reset();
-    }
-    private void flushData() {
-        try {
-            zipOut.finish();
-        } catch (IOException ee) {
-            throw new RuntimeException(ee); // cannot happen
-        }
-    }
-    private int getByteSize() {
-        return byteSizer.getSize();
-    }
-    private int getZipSize() {
-        flushData();
-        return zipSizer.getSize();
-    }
-
-
-    /// Stress-test helpers.
-
-    void addStressSeed(int x) {
-        if (stress == null)  return;
-        stress.setSeed(x + ((long)stress.nextInt() << 32));
-    }
-
-    // Pick a random pop-coding.
-    private CodingMethod stressPopCoding(CodingMethod coding) {
-        assert(stress != null);  // this method is only for testing
-        // Don't turn it into a pop coding if it's already something special.
-        if (!(coding instanceof Coding))  return coding;
-        Coding valueCoding = ((Coding)coding).getValueCoding();
-        Histogram hist = getValueHistogram();
-        int fVlen = stressLen(hist.getTotalLength());
-        if (fVlen == 0)  return coding;
-        List<Integer> popvals = new ArrayList<>();
-        if (stress.nextBoolean()) {
-            // Build the population from the value list.
-            Set<Integer> popset = new HashSet<>();
-            for (int i = start; i < end; i++) {
-                if (popset.add(values[i]))  popvals.add(values[i]);
-            }
-        } else {
-            int[][] matrix = hist.getMatrix();
-            for (int mrow = 0; mrow < matrix.length; mrow++) {
-                int[] row = matrix[mrow];
-                for (int mcol = 1; mcol < row.length; mcol++) {
-                    popvals.add(row[mcol]);
-                }
-            }
-        }
-        int reorder = stress.nextInt();
-        if ((reorder & 7) <= 2) {
-            // Lose the order.
-            Collections.shuffle(popvals, stress);
-        } else {
-            // Keep the order, mostly.
-            if (((reorder >>>= 3) & 7) <= 2)  Collections.sort(popvals);
-            if (((reorder >>>= 3) & 7) <= 2)  Collections.reverse(popvals);
-            if (((reorder >>>= 3) & 7) <= 2)  Collections.rotate(popvals, stressLen(popvals.size()));
-        }
-        if (popvals.size() > fVlen) {
-            // Cut the list down.
-            if (((reorder >>>= 3) & 7) <= 2) {
-                // Cut at end.
-                popvals.subList(fVlen,   popvals.size()).clear();
-            } else {
-                // Cut at start.
-                popvals.subList(0, popvals.size()-fVlen).clear();
-            }
-        }
-        fVlen = popvals.size();
-        int[] fvals = new int[1+fVlen];
-        for (int i = 0; i < fVlen; i++) {
-            fvals[1+i] = (popvals.get(i)).intValue();
-        }
-        PopulationCoding pop = new PopulationCoding();
-        pop.setFavoredValues(fvals, fVlen);
-        int[] lvals = PopulationCoding.LValuesCoded;
-        for (int i = 0; i < lvals.length / 2; i++) {
-            int popl = lvals[stress.nextInt(lvals.length)];
-            if (popl < 0)  continue;
-            if (PopulationCoding.fitTokenCoding(fVlen, popl) != null) {
-                pop.setL(popl);
-                break;
-            }
-        }
-        if (pop.tokenCoding == null) {
-            int lmin = fvals[1], lmax = lmin;
-            for (int i = 2; i <= fVlen; i++) {
-                int val = fvals[i];
-                if (lmin > val)  lmin = val;
-                if (lmax < val)  lmax = val;
-            }
-            pop.tokenCoding = stressCoding(lmin, lmax);
-        }
-
-        computePopSizePrivate(pop, valueCoding, valueCoding);
-        return pop;
-    }
-
-    // Pick a random adaptive coding.
-    private CodingMethod stressAdaptiveCoding(CodingMethod coding) {
-        assert(stress != null);  // this method is only for testing
-        // Don't turn it into a run coding if it's already something special.
-        if (!(coding instanceof Coding))  return coding;
-        Coding plainCoding = (Coding)coding;
-        int len = end-start;
-        if (len < 2)  return coding;
-        // Decide how many spans we'll create.
-        int spanlen = stressLen(len-1)+1;
-        if (spanlen == len)  return coding;
-        try {
-            assert(!disableRunCoding);
-            disableRunCoding = true;  // temporary, while I decide spans
-            int[] allValues = values.clone();
-            CodingMethod result = null;
-            int scan  = this.end;
-            int lstart = this.start;
-            for (int split; scan > lstart; scan = split) {
-                int thisspan;
-                int rand = (scan - lstart < 100)? -1: stress.nextInt();
-                if ((rand & 7) != 0) {
-                    thisspan = (spanlen==1? spanlen: stressLen(spanlen-1)+1);
-                } else {
-                    // Every so often generate a value based on KX/KB format.
-                    int KX = (rand >>>= 3) & AdaptiveCoding.KX_MAX;
-                    int KB = (rand >>>= 3) & AdaptiveCoding.KB_MAX;
-                    for (;;) {
-                        thisspan = AdaptiveCoding.decodeK(KX, KB);
-                        if (thisspan <= scan - lstart)  break;
-                        // Try smaller and smaller codings:
-                        if (KB != AdaptiveCoding.KB_DEFAULT)
-                            KB = AdaptiveCoding.KB_DEFAULT;
-                        else
-                            KX -= 1;
-                    }
-                    //System.out.println("KX="+KX+" KB="+KB+" K="+thisspan);
-                    assert(AdaptiveCoding.isCodableLength(thisspan));
-                }
-                if (thisspan > scan - lstart)  thisspan = scan - lstart;
-                while (!AdaptiveCoding.isCodableLength(thisspan)) {
-                    --thisspan;
-                }
-                split = scan - thisspan;
-                assert(split < scan);
-                assert(split >= lstart);
-                // Choose a coding for the span [split..scan).
-                CodingMethod sc = choose(allValues, split, scan, plainCoding);
-                if (result == null) {
-                    result = sc;  // the caboose
-                } else {
-                    result = new AdaptiveCoding(scan-split, sc, result);
-                }
-            }
-            return result;
-        } finally {
-            disableRunCoding = false; // return to normal value
-        }
-    }
-
-    // Return a random value in [0..len], gently biased toward extremes.
-    private Coding stressCoding(int min, int max) {
-        assert(stress != null);  // this method is only for testing
-        for (int i = 0; i < 100; i++) {
-            Coding c = Coding.of(stress.nextInt(Coding.B_MAX)+1,
-                                 stress.nextInt(Coding.H_MAX)+1,
-                                 stress.nextInt(Coding.S_MAX+1));
-            if (c.B() == 1)  c = c.setH(256);
-            if (c.H() == 256 && c.B() >= 5)  c = c.setB(4);
-            if (stress.nextBoolean()) {
-                Coding dc = c.setD(1);
-                if (dc.canRepresent(min, max))  return dc;
-            }
-            if (c.canRepresent(min, max))  return c;
-        }
-        return BandStructure.UNSIGNED5;
-    }
-
-    // Return a random value in [0..len], gently biased toward extremes.
-    private int stressLen(int len) {
-        assert(stress != null);  // this method is only for testing
-        assert(len >= 0);
-        int rand = stress.nextInt(100);
-        if (rand < 20)
-            return Math.min(len/5, rand);
-        else if (rand < 40)
-            return len;
-        else
-            return stress.nextInt(len);
-    }
-
-    // For debug only.
-/*
-    public static
-    int[] readValuesFrom(InputStream instr) {
-        return readValuesFrom(new InputStreamReader(instr));
-    }
-    public static
-    int[] readValuesFrom(Reader inrdr) {
-        inrdr = new BufferedReader(inrdr);
-        final StreamTokenizer in = new StreamTokenizer(inrdr);
-        final int TT_NOTHING = -99;
-        in.commentChar('#');
-        return readValuesFrom(new Iterator() {
-            int token = TT_NOTHING;
-            private int getToken() {
-                if (token == TT_NOTHING) {
-                    try {
-                        token = in.nextToken();
-                        assert(token != TT_NOTHING);
-                    } catch (IOException ee) {
-                        throw new RuntimeException(ee);
-                    }
-                }
-                return token;
-            }
-            public boolean hasNext() {
-                return getToken() != StreamTokenizer.TT_EOF;
-            }
-            public Object next() {
-                int ntok = getToken();
-                token = TT_NOTHING;
-                switch (ntok) {
-                case StreamTokenizer.TT_EOF:
-                    throw new NoSuchElementException();
-                case StreamTokenizer.TT_NUMBER:
-                    return Integer.valueOf((int) in.nval);
-                default:
-                    assert(false);
-                    return null;
-                }
-            }
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
-        });
-    }
-    public static
-    int[] readValuesFrom(Iterator iter) {
-        return readValuesFrom(iter, 0);
-    }
-    public static
-    int[] readValuesFrom(Iterator iter, int initSize) {
-        int[] na = new int[Math.max(10, initSize)];
-        int np = 0;
-        while (iter.hasNext()) {
-            Integer val = (Integer) iter.next();
-            if (np == na.length) {
-                na = BandStructure.realloc(na);
-            }
-            na[np++] = val.intValue();
-        }
-        if (np != na.length) {
-            na = BandStructure.realloc(na, np);
-        }
-        return na;
-    }
-
-    public static
-    void main(String[] av) throws IOException {
-        int effort = MID_EFFORT;
-        int ap = 0;
-        if (ap < av.length && av[ap].equals("-e")) {
-            ap++;
-            effort = Integer.parseInt(av[ap++]);
-        }
-        int verbose = 1;
-        if (ap < av.length && av[ap].equals("-v")) {
-            ap++;
-            verbose = Integer.parseInt(av[ap++]);
-        }
-        Coding[] bcs = BandStructure.getBasicCodings();
-        CodingChooser cc = new CodingChooser(effort, bcs);
-        if (ap < av.length && av[ap].equals("-p")) {
-            ap++;
-            cc.optUsePopulationCoding = false;
-        }
-        if (ap < av.length && av[ap].equals("-a")) {
-            ap++;
-            cc.optUseAdaptiveCoding = false;
-        }
-        cc.verbose = verbose;
-        int[] values = readValuesFrom(System.in);
-        int[] sizes = {0,0};
-        CodingMethod cm = cc.choose(values, BandStructure.UNSIGNED5, sizes);
-        System.out.println("size: "+sizes[BYTE_SIZE]+"/zs="+sizes[ZIP_SIZE]);
-        System.out.println(cm);
-    }
-//*/
-
-}
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/CodingMethod.java	Mon Dec 09 15:28:46 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * 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
- * 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 java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Interface for encoding and decoding int arrays using bytewise codes.
- * @author John Rose
- */
-interface CodingMethod {
-    // Read and write an array of ints from/to a stream.
-    public void readArrayFrom(InputStream in, int[] a, int start, int end) throws IOException;
-    public void writeArrayTo(OutputStream out, int[] a, int start, int end) throws IOException;
-
-    // how to express me in a band header?
-    public byte[] getMetaCoding(Coding dflt);
-}
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/ConstantPool.java	Mon Dec 09 15:28:46 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1658 +0,0 @@
-/*
- * Copyright (c) 2001, 2013, 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 java.util.AbstractList;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
-import static com.sun.java.util.jar.pack.Constants.*;
-
-/**
- * Representation of constant pool entries and indexes.
- * @author John Rose
- */
-abstract
-class ConstantPool {
-    private ConstantPool() {}  // do not instantiate
-
-    static int verbose() {
-        return Utils.currentPropMap().getInteger(Utils.DEBUG_VERBOSE);
-    }
-
-    /** 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) {
-        Map<String, Utf8Entry> utf8Entries  = Utils.getTLGlobals().getUtf8Entries();
-        Utf8Entry e = utf8Entries.get(value);
-        if (e == null) {
-            e = new Utf8Entry(value);
-            utf8Entries.put(e.stringValue(), e);
-        }
-        return e;
-    }
-    /** Factory for Class constants. */
-    public static ClassEntry getClassEntry(String name) {
-        Map<String, ClassEntry> classEntries = Utils.getTLGlobals().getClassEntries();
-        ClassEntry e = classEntries.get(name);
-        if (e == null) {
-            e = new ClassEntry(getUtf8Entry(name));
-            assert(name.equals(e.stringValue()));
-            classEntries.put(e.stringValue(), e);
-        }
-        return e;
-    }
-    /** Factory for literal constants (String, Integer, etc.). */
-    public static LiteralEntry getLiteralEntry(Comparable<?> value) {
-        Map<Object, LiteralEntry> literalEntries = Utils.getTLGlobals().getLiteralEntries();
-        LiteralEntry e = literalEntries.get(value);
-        if (e == null) {
-            if (value instanceof String)
-                e = new StringEntry(getUtf8Entry((String)value));
-            else
-                e = new NumberEntry((Number)value);
-            literalEntries.put(value, e);
-        }
-        return e;
-    }
-    /** Factory for literal constants (String, Integer, etc.). */
-    public static StringEntry getStringEntry(String value) {
-        return (StringEntry) getLiteralEntry(value);
-    }
-
-    /** Factory for signature (type) constants. */
-    public static SignatureEntry getSignatureEntry(String type) {
-        Map<String, SignatureEntry> signatureEntries = Utils.getTLGlobals().getSignatureEntries();
-        SignatureEntry e = signatureEntries.get(type);
-        if (e == null) {
-            e = new SignatureEntry(type);
-            assert(e.stringValue().equals(type));
-            signatureEntries.put(type, e);
-        }
-        return e;
-    }
-    // Convenience overloading.
-    public static SignatureEntry getSignatureEntry(Utf8Entry formRef, ClassEntry[] classRefs) {
-        return getSignatureEntry(SignatureEntry.stringValueOf(formRef, classRefs));
-    }
-
-    /** Factory for descriptor (name-and-type) constants. */
-    public static DescriptorEntry getDescriptorEntry(Utf8Entry nameRef, SignatureEntry typeRef) {
-        Map<String, DescriptorEntry> descriptorEntries = Utils.getTLGlobals().getDescriptorEntries();
-        String key = DescriptorEntry.stringValueOf(nameRef, typeRef);
-        DescriptorEntry e = descriptorEntries.get(key);
-        if (e == null) {
-            e = new DescriptorEntry(nameRef, typeRef);
-            assert(e.stringValue().equals(key))
-                : (e.stringValue()+" != "+(key));
-            descriptorEntries.put(key, e);
-        }
-        return e;
-    }
-    // Convenience overloading.
-    public static DescriptorEntry getDescriptorEntry(Utf8Entry nameRef, Utf8Entry typeRef) {
-        return getDescriptorEntry(nameRef, getSignatureEntry(typeRef.stringValue()));
-    }
-
-    /** Factory for member reference constants. */
-    public static MemberEntry getMemberEntry(byte tag, ClassEntry classRef, DescriptorEntry descRef) {
-        Map<String, MemberEntry> memberEntries = Utils.getTLGlobals().getMemberEntries();
-        String key = MemberEntry.stringValueOf(tag, classRef, descRef);
-        MemberEntry e = memberEntries.get(key);
-        if (e == null) {
-            e = new MemberEntry(tag, classRef, descRef);
-            assert(e.stringValue().equals(key))
-                : (e.stringValue()+" != "+(key));
-            memberEntries.put(key, e);
-        }
-        return e;
-    }
-
-    /** Factory for MethodHandle constants. */
-    public static MethodHandleEntry getMethodHandleEntry(byte refKind, MemberEntry memRef) {
-        Map<String, MethodHandleEntry> methodHandleEntries = Utils.getTLGlobals().getMethodHandleEntries();
-        String key = MethodHandleEntry.stringValueOf(refKind, memRef);
-        MethodHandleEntry e = methodHandleEntries.get(key);
-        if (e == null) {
-            e = new MethodHandleEntry(refKind, memRef);
-            assert(e.stringValue().equals(key));
-            methodHandleEntries.put(key, e);
-        }
-        return e;
-    }
-
-    /** Factory for MethodType constants. */
-    public static MethodTypeEntry getMethodTypeEntry(SignatureEntry sigRef) {
-        Map<String, MethodTypeEntry> methodTypeEntries = Utils.getTLGlobals().getMethodTypeEntries();
-        String key = sigRef.stringValue();
-        MethodTypeEntry e = methodTypeEntries.get(key);
-        if (e == null) {
-            e = new MethodTypeEntry(sigRef);
-            assert(e.stringValue().equals(key));
-            methodTypeEntries.put(key, e);
-        }
-        return e;
-    }
-    public static MethodTypeEntry getMethodTypeEntry(Utf8Entry typeRef) {
-        return getMethodTypeEntry(getSignatureEntry(typeRef.stringValue()));
-    }
-
-    /** Factory for InvokeDynamic constants. */
-    public static InvokeDynamicEntry getInvokeDynamicEntry(BootstrapMethodEntry bssRef, DescriptorEntry descRef) {
-        Map<String, InvokeDynamicEntry> invokeDynamicEntries = Utils.getTLGlobals().getInvokeDynamicEntries();
-        String key = InvokeDynamicEntry.stringValueOf(bssRef, descRef);
-        InvokeDynamicEntry e = invokeDynamicEntries.get(key);
-        if (e == null) {
-            e = new InvokeDynamicEntry(bssRef, descRef);
-            assert(e.stringValue().equals(key));
-            invokeDynamicEntries.put(key, e);
-        }
-        return e;
-    }
-
-    /** Factory for BootstrapMethod pseudo-constants. */
-    public static BootstrapMethodEntry getBootstrapMethodEntry(MethodHandleEntry bsmRef, Entry[] argRefs) {
-        Map<String, BootstrapMethodEntry> bootstrapMethodEntries = Utils.getTLGlobals().getBootstrapMethodEntries();
-        String key = BootstrapMethodEntry.stringValueOf(bsmRef, argRefs);
-        BootstrapMethodEntry e = bootstrapMethodEntries.get(key);
-        if (e == null) {
-            e = new BootstrapMethodEntry(bsmRef, argRefs);
-            assert(e.stringValue().equals(key));
-            bootstrapMethodEntries.put(key, e);
-        }
-        return e;
-    }
-
-
-    /** Entries in the constant pool. */
-    public abstract static
-    class Entry implements Comparable<Object> {
-        protected final byte tag;       // a CONSTANT_foo code
-        protected int valueHash;        // cached hashCode
-
-        protected Entry(byte tag) {
-            this.tag = tag;
-        }
-
-        public final byte getTag() {
-            return tag;
-        }
-
-        public final boolean tagEquals(int tag) {
-            return getTag() == tag;
-        }
-
-        public Entry getRef(int i) {
-            return null;
-        }
-
-        public boolean eq(Entry that) {  // same reference
-            assert(that != null);
-            return this == that || this.equals(that);
-        }
-
-        // Equality of Entries is value-based.
-        public abstract boolean equals(Object o);
-        public final int hashCode() {
-            if (valueHash == 0) {
-                valueHash = computeValueHash();
-                if (valueHash == 0)  valueHash = 1;
-            }
-            return valueHash;
-        }
-        protected abstract int computeValueHash();
-
-        public abstract int compareTo(Object o);
-
-        protected int superCompareTo(Object o) {
-            Entry that = (Entry) o;
-
-            if (this.tag != that.tag) {
-                return TAG_ORDER[this.tag] - TAG_ORDER[that.tag];
-            }
-
-            return 0;  // subclasses must refine this
-        }
-
-        public final boolean isDoubleWord() {
-            return tag == CONSTANT_Double || tag == CONSTANT_Long;
-        }
-
-        public final boolean tagMatches(int matchTag) {
-            if (tag == matchTag)
-                return true;
-            byte[] allowedTags;
-            switch (matchTag) {
-                case CONSTANT_All:
-                    return true;
-                case CONSTANT_Signature:
-                    return tag == CONSTANT_Utf8;  // format check also?
-                case CONSTANT_LoadableValue:
-                    allowedTags = LOADABLE_VALUE_TAGS;
-                    break;
-                case CONSTANT_AnyMember:
-                    allowedTags = ANY_MEMBER_TAGS;
-                    break;
-                case CONSTANT_FieldSpecific:
-                    allowedTags = FIELD_SPECIFIC_TAGS;
-                    break;
-                default:
-                    return false;
-            }
-            for (byte b : allowedTags) {
-                if (b == tag)
-                    return true;
-            }
-            return false;
-        }
-
-        public String toString() {
-            String valuePrint = stringValue();
-            if (verbose() > 4) {
-                if (valueHash != 0)
-                    valuePrint += " hash="+valueHash;
-                valuePrint += " id="+System.identityHashCode(this);
-            }
-            return tagName(tag)+"="+valuePrint;
-        }
-        public abstract String stringValue();
-    }
-
-    public static
-    class Utf8Entry extends Entry {
-        final String value;
-
-        Utf8Entry(String value) {
-            super(CONSTANT_Utf8);
-            this.value = value.intern();
-            hashCode();  // force computation of valueHash
-        }
-        protected int computeValueHash() {
-            return value.hashCode();
-        }
-        public boolean equals(Object o) {
-            // Use reference equality of interned strings:
-            return (o != null && o.getClass() == Utf8Entry.class
-                    && ((Utf8Entry) o).value.equals(value));
-        }
-        public int compareTo(Object o) {
-            int x = superCompareTo(o);
-            if (x == 0) {
-                x = value.compareTo(((Utf8Entry)o).value);
-            }
-            return x;
-        }
-        public String stringValue() {
-            return value;
-        }
-    }
-
-    static boolean isMemberTag(byte tag) {
-        switch (tag) {
-        case CONSTANT_Fieldref:
-        case CONSTANT_Methodref:
-        case CONSTANT_InterfaceMethodref:
-            return true;
-        }
-        return false;
-    }
-
-    static byte numberTagOf(Number value) {
-        if (value instanceof Integer)  return CONSTANT_Integer;
-        if (value instanceof Float)    return CONSTANT_Float;
-        if (value instanceof Long)     return CONSTANT_Long;
-        if (value instanceof Double)   return CONSTANT_Double;
-        throw new RuntimeException("bad literal value "+value);
-    }
-
-    static boolean isRefKind(byte refKind) {
-        return (REF_getField <= refKind && refKind <= REF_invokeInterface);
-    }
-
-    public abstract static
-    class LiteralEntry extends Entry {
-        protected LiteralEntry(byte tag) {
-