rt/emul/compact/src/main/java/sun/invoke/anon/ConstantPoolPatch.java
branchjdk8
changeset 1651 5c990ed353e9
parent 1650 6799184bf769
child 1652 8fb89a569621
     1.1 --- a/rt/emul/compact/src/main/java/sun/invoke/anon/ConstantPoolPatch.java	Sun Aug 10 05:56:32 2014 +0200
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,503 +0,0 @@
     1.4 -/*
     1.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
     1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 - *
     1.8 - * This code is free software; you can redistribute it and/or modify it
     1.9 - * under the terms of the GNU General Public License version 2 only, as
    1.10 - * published by the Free Software Foundation.  Oracle designates this
    1.11 - * particular file as subject to the "Classpath" exception as provided
    1.12 - * by Oracle in the LICENSE file that accompanied this code.
    1.13 - *
    1.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 - * version 2 for more details (a copy is included in the LICENSE file that
    1.18 - * accompanied this code).
    1.19 - *
    1.20 - * You should have received a copy of the GNU General Public License version
    1.21 - * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 - *
    1.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 - * or visit www.oracle.com if you need additional information or have any
    1.26 - * questions.
    1.27 - */
    1.28 -
    1.29 -package sun.invoke.anon;
    1.30 -
    1.31 -import java.io.IOException;
    1.32 -import java.io.OutputStream;
    1.33 -import java.util.Arrays;
    1.34 -import java.util.HashSet;
    1.35 -import java.util.IdentityHashMap;
    1.36 -import java.util.Map;
    1.37 -
    1.38 -import static sun.invoke.anon.ConstantPoolVisitor.*;
    1.39 -
    1.40 -/** A class and its patched constant pool.
    1.41 - *
    1.42 - *  This class allow to modify (patch) a constant pool
    1.43 - *  by changing the value of its entry.
    1.44 - *  Entry are referenced using index that can be get
    1.45 - *  by parsing the constant pool using
    1.46 - *  {@link ConstantPoolParser#parse(ConstantPoolVisitor)}.
    1.47 - *
    1.48 - * @see ConstantPoolVisitor
    1.49 - * @see ConstantPoolParser#createPatch()
    1.50 - */
    1.51 -public class ConstantPoolPatch {
    1.52 -    final ConstantPoolParser outer;
    1.53 -    final Object[] patchArray;
    1.54 -
    1.55 -    ConstantPoolPatch(ConstantPoolParser outer) {
    1.56 -        this.outer      = outer;
    1.57 -        this.patchArray = new Object[outer.getLength()];
    1.58 -    }
    1.59 -
    1.60 -    /** Create a {@link ConstantPoolParser} and
    1.61 -     *  a {@link ConstantPoolPatch} in one step.
    1.62 -     *  Equivalent to {@code new ConstantPoolParser(classFile).createPatch()}.
    1.63 -     *
    1.64 -     * @param classFile an array of bytes containing a class.
    1.65 -     * @see #ConstantPoolParser(Class)
    1.66 -     */
    1.67 -    public ConstantPoolPatch(byte[] classFile) throws InvalidConstantPoolFormatException {
    1.68 -        this(new ConstantPoolParser(classFile));
    1.69 -    }
    1.70 -
    1.71 -    /** Create a {@link ConstantPoolParser} and
    1.72 -     *  a {@link ConstantPoolPatch} in one step.
    1.73 -     *  Equivalent to {@code new ConstantPoolParser(templateClass).createPatch()}.
    1.74 -     *
    1.75 -     * @param templateClass the class to parse.
    1.76 -     * @see #ConstantPoolParser(Class)
    1.77 -     */
    1.78 -    public ConstantPoolPatch(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
    1.79 -        this(new ConstantPoolParser(templateClass));
    1.80 -    }
    1.81 -
    1.82 -
    1.83 -    /** Creates a patch from an existing patch.
    1.84 -     *  All changes are copied from that patch.
    1.85 -     * @param patch a patch
    1.86 -     *
    1.87 -     * @see ConstantPoolParser#createPatch()
    1.88 -     */
    1.89 -    public ConstantPoolPatch(ConstantPoolPatch patch) {
    1.90 -        outer      = patch.outer;
    1.91 -        patchArray = patch.patchArray.clone();
    1.92 -    }
    1.93 -
    1.94 -    /** Which parser built this patch? */
    1.95 -    public ConstantPoolParser getParser() {
    1.96 -        return outer;
    1.97 -    }
    1.98 -
    1.99 -    /** Report the tag at the given index in the constant pool. */
   1.100 -    public byte getTag(int index) {
   1.101 -        return outer.getTag(index);
   1.102 -    }
   1.103 -
   1.104 -    /** Report the current patch at the given index of the constant pool.
   1.105 -     *  Null means no patch will be made.
   1.106 -     *  To observe the unpatched entry at the given index, use
   1.107 -     *  {@link #getParser()}{@code .}@link ConstantPoolParser#parse(ConstantPoolVisitor)}
   1.108 -     */
   1.109 -    public Object getPatch(int index) {
   1.110 -        Object value = patchArray[index];
   1.111 -        if (value == null)  return null;
   1.112 -        switch (getTag(index)) {
   1.113 -        case CONSTANT_Fieldref:
   1.114 -        case CONSTANT_Methodref:
   1.115 -        case CONSTANT_InterfaceMethodref:
   1.116 -            if (value instanceof String)
   1.117 -                value = stripSemis(2, (String) value);
   1.118 -            break;
   1.119 -        case CONSTANT_NameAndType:
   1.120 -            if (value instanceof String)
   1.121 -                value = stripSemis(1, (String) value);
   1.122 -            break;
   1.123 -        }
   1.124 -        return value;
   1.125 -    }
   1.126 -
   1.127 -    /** Clear all patches. */
   1.128 -    public void clear() {
   1.129 -        Arrays.fill(patchArray, null);
   1.130 -    }
   1.131 -
   1.132 -    /** Clear one patch. */
   1.133 -    public void clear(int index) {
   1.134 -        patchArray[index] = null;
   1.135 -    }
   1.136 -
   1.137 -    /** Produce the patches as an array. */
   1.138 -    public Object[] getPatches() {
   1.139 -        return patchArray.clone();
   1.140 -    }
   1.141 -
   1.142 -    /** Produce the original constant pool as an array. */
   1.143 -    public Object[] getOriginalCP() throws InvalidConstantPoolFormatException {
   1.144 -        return getOriginalCP(0, patchArray.length, -1);
   1.145 -    }
   1.146 -
   1.147 -    /** Walk the constant pool, applying patches using the given map.
   1.148 -     *
   1.149 -     * @param utf8Map Utf8 strings to modify, if encountered
   1.150 -     * @param classMap Classes (or their names) to modify, if encountered
   1.151 -     * @param valueMap Constant values to modify, if encountered
   1.152 -     * @param deleteUsedEntries if true, delete map entries that are used
   1.153 -     */
   1.154 -    public void putPatches(final Map<String,String> utf8Map,
   1.155 -                           final Map<String,Object> classMap,
   1.156 -                           final Map<Object,Object> valueMap,
   1.157 -                           boolean deleteUsedEntries) throws InvalidConstantPoolFormatException {
   1.158 -        final HashSet<String> usedUtf8Keys;
   1.159 -        final HashSet<String> usedClassKeys;
   1.160 -        final HashSet<Object> usedValueKeys;
   1.161 -        if (deleteUsedEntries) {
   1.162 -            usedUtf8Keys  = (utf8Map  == null) ? null : new HashSet<String>();
   1.163 -            usedClassKeys = (classMap == null) ? null : new HashSet<String>();
   1.164 -            usedValueKeys = (valueMap == null) ? null : new HashSet<Object>();
   1.165 -        } else {
   1.166 -            usedUtf8Keys = null;
   1.167 -            usedClassKeys = null;
   1.168 -            usedValueKeys = null;
   1.169 -        }
   1.170 -
   1.171 -        outer.parse(new ConstantPoolVisitor() {
   1.172 -
   1.173 -            @Override
   1.174 -            public void visitUTF8(int index, byte tag, String utf8) {
   1.175 -                putUTF8(index, utf8Map.get(utf8));
   1.176 -                if (usedUtf8Keys != null)  usedUtf8Keys.add(utf8);
   1.177 -            }
   1.178 -
   1.179 -            @Override
   1.180 -            public void visitConstantValue(int index, byte tag, Object value) {
   1.181 -                putConstantValue(index, tag, valueMap.get(value));
   1.182 -                if (usedValueKeys != null)  usedValueKeys.add(value);
   1.183 -            }
   1.184 -
   1.185 -            @Override
   1.186 -            public void visitConstantString(int index, byte tag, String name, int nameIndex) {
   1.187 -                if (tag == CONSTANT_Class) {
   1.188 -                    putConstantValue(index, tag, classMap.get(name));
   1.189 -                    if (usedClassKeys != null)  usedClassKeys.add(name);
   1.190 -                } else {
   1.191 -                    assert(tag == CONSTANT_String);
   1.192 -                    visitConstantValue(index, tag, name);
   1.193 -                }
   1.194 -            }
   1.195 -        });
   1.196 -        if (usedUtf8Keys != null)   utf8Map.keySet().removeAll(usedUtf8Keys);
   1.197 -        if (usedClassKeys != null)  classMap.keySet().removeAll(usedClassKeys);
   1.198 -        if (usedValueKeys != null)  valueMap.keySet().removeAll(usedValueKeys);
   1.199 -    }
   1.200 -
   1.201 -    Object[] getOriginalCP(final int startIndex,
   1.202 -                           final int endIndex,
   1.203 -                           final int tagMask) throws InvalidConstantPoolFormatException {
   1.204 -        final Object[] cpArray = new Object[endIndex - startIndex];
   1.205 -        outer.parse(new ConstantPoolVisitor() {
   1.206 -
   1.207 -            void show(int index, byte tag, Object value) {
   1.208 -                if (index < startIndex || index >= endIndex)  return;
   1.209 -                if (((1 << tag) & tagMask) == 0)  return;
   1.210 -                cpArray[index - startIndex] = value;
   1.211 -            }
   1.212 -
   1.213 -            @Override
   1.214 -            public void visitUTF8(int index, byte tag, String utf8) {
   1.215 -                show(index, tag, utf8);
   1.216 -            }
   1.217 -
   1.218 -            @Override
   1.219 -            public void visitConstantValue(int index, byte tag, Object value) {
   1.220 -                assert(tag != CONSTANT_String);
   1.221 -                show(index, tag, value);
   1.222 -            }
   1.223 -
   1.224 -            @Override
   1.225 -            public void visitConstantString(int index, byte tag,
   1.226 -                                            String value, int j) {
   1.227 -                show(index, tag, value);
   1.228 -            }
   1.229 -
   1.230 -            @Override
   1.231 -            public void visitMemberRef(int index, byte tag,
   1.232 -                    String className, String memberName,
   1.233 -                    String signature,
   1.234 -                    int j, int k) {
   1.235 -                show(index, tag, new String[]{ className, memberName, signature });
   1.236 -            }
   1.237 -
   1.238 -            @Override
   1.239 -            public void visitDescriptor(int index, byte tag,
   1.240 -                    String memberName, String signature,
   1.241 -                    int j, int k) {
   1.242 -                show(index, tag, new String[]{ memberName, signature });
   1.243 -            }
   1.244 -        });
   1.245 -        return cpArray;
   1.246 -    }
   1.247 -
   1.248 -    /** Write the head (header plus constant pool)
   1.249 -     *  of the patched class file to the indicated stream.
   1.250 -     */
   1.251 -    void writeHead(OutputStream out) throws IOException {
   1.252 -        outer.writePatchedHead(out, patchArray);
   1.253 -    }
   1.254 -
   1.255 -    /** Write the tail (everything after the constant pool)
   1.256 -     *  of the patched class file to the indicated stream.
   1.257 -     */
   1.258 -    void writeTail(OutputStream out) throws IOException {
   1.259 -        outer.writeTail(out);
   1.260 -    }
   1.261 -
   1.262 -    private void checkConstantTag(byte tag, Object value) {
   1.263 -        if (value == null)
   1.264 -            throw new IllegalArgumentException(
   1.265 -                    "invalid null constant value");
   1.266 -        if (classForTag(tag) != value.getClass())
   1.267 -            throw new IllegalArgumentException(
   1.268 -                    "invalid constant value"
   1.269 -                    + (tag == CONSTANT_None ? ""
   1.270 -                        : " for tag "+tagName(tag))
   1.271 -                    + " of class "+value.getClass());
   1.272 -    }
   1.273 -
   1.274 -    private void checkTag(int index, byte putTag) {
   1.275 -        byte tag = outer.tags[index];
   1.276 -        if (tag != putTag)
   1.277 -            throw new IllegalArgumentException(
   1.278 -                "invalid put operation"
   1.279 -                + " for " + tagName(putTag)
   1.280 -                + " at index " + index + " found " + tagName(tag));
   1.281 -    }
   1.282 -
   1.283 -    private void checkTagMask(int index, int tagBitMask) {
   1.284 -        byte tag = outer.tags[index];
   1.285 -        int tagBit = ((tag & 0x1F) == tag) ? (1 << tag) : 0;
   1.286 -        if ((tagBit & tagBitMask) == 0)
   1.287 -            throw new IllegalArgumentException(
   1.288 -                "invalid put operation"
   1.289 -                + " at index " + index + " found " + tagName(tag));
   1.290 -    }
   1.291 -
   1.292 -    private static void checkMemberName(String memberName) {
   1.293 -        if (memberName.indexOf(';') >= 0)
   1.294 -            throw new IllegalArgumentException("memberName " + memberName + " contains a ';'");
   1.295 -    }
   1.296 -
   1.297 -    /** Set the entry of the constant pool indexed by index to
   1.298 -     *  a new string.
   1.299 -     *
   1.300 -     * @param index an index to a constant pool entry containing a
   1.301 -     *        {@link ConstantPoolVisitor#CONSTANT_Utf8} value.
   1.302 -     * @param utf8 a string
   1.303 -     *
   1.304 -     * @see ConstantPoolVisitor#visitUTF8(int, byte, String)
   1.305 -     */
   1.306 -    public void putUTF8(int index, String utf8) {
   1.307 -        if (utf8 == null) { clear(index); return; }
   1.308 -        checkTag(index, CONSTANT_Utf8);
   1.309 -        patchArray[index] = utf8;
   1.310 -    }
   1.311 -
   1.312 -    /** Set the entry of the constant pool indexed by index to
   1.313 -     *  a new value, depending on its dynamic type.
   1.314 -     *
   1.315 -     * @param index an index to a constant pool entry containing a
   1.316 -     *        one of the following structures:
   1.317 -     *        {@link ConstantPoolVisitor#CONSTANT_Integer},
   1.318 -     *        {@link ConstantPoolVisitor#CONSTANT_Float},
   1.319 -     *        {@link ConstantPoolVisitor#CONSTANT_Long},
   1.320 -     *        {@link ConstantPoolVisitor#CONSTANT_Double},
   1.321 -     *        {@link ConstantPoolVisitor#CONSTANT_String}, or
   1.322 -     *        {@link ConstantPoolVisitor#CONSTANT_Class}
   1.323 -     * @param value a boxed int, float, long or double; or a string or class object
   1.324 -     * @throws IllegalArgumentException if the type of the constant does not
   1.325 -     *         match the constant pool entry type,
   1.326 -     *         as reported by {@link #getTag(int)}
   1.327 -     *
   1.328 -     * @see #putConstantValue(int, byte, Object)
   1.329 -     * @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
   1.330 -     * @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
   1.331 -     */
   1.332 -    public void putConstantValue(int index, Object value) {
   1.333 -        if (value == null) { clear(index); return; }
   1.334 -        byte tag = tagForConstant(value.getClass());
   1.335 -        checkConstantTag(tag, value);
   1.336 -        checkTag(index, tag);
   1.337 -        patchArray[index] = value;
   1.338 -    }
   1.339 -
   1.340 -    /** Set the entry of the constant pool indexed by index to
   1.341 -     *  a new value.
   1.342 -     *
   1.343 -     * @param index an index to a constant pool entry matching the given tag
   1.344 -     * @param tag one of the following values:
   1.345 -     *        {@link ConstantPoolVisitor#CONSTANT_Integer},
   1.346 -     *        {@link ConstantPoolVisitor#CONSTANT_Float},
   1.347 -     *        {@link ConstantPoolVisitor#CONSTANT_Long},
   1.348 -     *        {@link ConstantPoolVisitor#CONSTANT_Double},
   1.349 -     *        {@link ConstantPoolVisitor#CONSTANT_String}, or
   1.350 -     *        {@link ConstantPoolVisitor#CONSTANT_Class}
   1.351 -     * @param value a boxed number, string, or class object
   1.352 -     * @throws IllegalArgumentException if the type of the constant does not
   1.353 -     *         match the constant pool entry type, or if a class name contains
   1.354 -     *         '/' or ';'
   1.355 -     *
   1.356 -     * @see #putConstantValue(int, Object)
   1.357 -     * @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
   1.358 -     * @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
   1.359 -     */
   1.360 -    public void putConstantValue(int index, byte tag, Object value) {
   1.361 -        if (value == null) { clear(index); return; }
   1.362 -        checkTag(index, tag);
   1.363 -        if (tag == CONSTANT_Class && value instanceof String) {
   1.364 -            checkClassName((String) value);
   1.365 -        } else if (tag == CONSTANT_String) {
   1.366 -            // the JVM accepts any object as a patch for a string
   1.367 -        } else {
   1.368 -            // make sure the incoming value is the right type
   1.369 -            checkConstantTag(tag, value);
   1.370 -        }
   1.371 -        checkTag(index, tag);
   1.372 -        patchArray[index] = value;
   1.373 -    }
   1.374 -
   1.375 -    /** Set the entry of the constant pool indexed by index to
   1.376 -     *  a new {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
   1.377 -     *
   1.378 -     * @param index an index to a constant pool entry containing a
   1.379 -     *        {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
   1.380 -     * @param memberName a memberName
   1.381 -     * @param signature a signature
   1.382 -     * @throws IllegalArgumentException if memberName contains the character ';'
   1.383 -     *
   1.384 -     * @see ConstantPoolVisitor#visitDescriptor(int, byte, String, String, int, int)
   1.385 -     */
   1.386 -    public void putDescriptor(int index, String memberName, String signature) {
   1.387 -        checkTag(index, CONSTANT_NameAndType);
   1.388 -        checkMemberName(memberName);
   1.389 -        patchArray[index] = addSemis(memberName, signature);
   1.390 -    }
   1.391 -
   1.392 -    /** Set the entry of the constant pool indexed by index to
   1.393 -     *  a new {@link ConstantPoolVisitor#CONSTANT_Fieldref},
   1.394 -     *  {@link ConstantPoolVisitor#CONSTANT_Methodref}, or
   1.395 -     *  {@link ConstantPoolVisitor#CONSTANT_InterfaceMethodref} value.
   1.396 -     *
   1.397 -     * @param index an index to a constant pool entry containing a member reference
   1.398 -     * @param className a class name
   1.399 -     * @param memberName a field or method name
   1.400 -     * @param signature a field or method signature
   1.401 -     * @throws IllegalArgumentException if memberName contains the character ';'
   1.402 -     *             or signature is not a correct signature
   1.403 -     *
   1.404 -     * @see ConstantPoolVisitor#visitMemberRef(int, byte, String, String, String, int, int)
   1.405 -     */
   1.406 -    public void putMemberRef(int index, byte tag,
   1.407 -                    String className, String memberName, String signature) {
   1.408 -        checkTagMask(tag, CONSTANT_MemberRef_MASK);
   1.409 -        checkTag(index, tag);
   1.410 -        checkClassName(className);
   1.411 -        checkMemberName(memberName);
   1.412 -        if (signature.startsWith("(") == (tag == CONSTANT_Fieldref))
   1.413 -            throw new IllegalArgumentException("bad signature: "+signature);
   1.414 -        patchArray[index] = addSemis(className, memberName, signature);
   1.415 -    }
   1.416 -
   1.417 -    static private final int CONSTANT_MemberRef_MASK =
   1.418 -              CONSTANT_Fieldref
   1.419 -            | CONSTANT_Methodref
   1.420 -            | CONSTANT_InterfaceMethodref;
   1.421 -
   1.422 -    private static final Map<Class<?>, Byte> CONSTANT_VALUE_CLASS_TAG
   1.423 -        = new IdentityHashMap<Class<?>, Byte>();
   1.424 -    private static final Class<?>[] CONSTANT_VALUE_CLASS = new Class<?>[16];
   1.425 -    static {
   1.426 -        Object[][] values = {
   1.427 -            {Integer.class, CONSTANT_Integer},
   1.428 -            {Long.class, CONSTANT_Long},
   1.429 -            {Float.class, CONSTANT_Float},
   1.430 -            {Double.class, CONSTANT_Double},
   1.431 -            {String.class, CONSTANT_String},
   1.432 -            {Class.class, CONSTANT_Class}
   1.433 -        };
   1.434 -        for (Object[] value : values) {
   1.435 -            Class<?> cls = (Class<?>)value[0];
   1.436 -            Byte     tag = (Byte) value[1];
   1.437 -            CONSTANT_VALUE_CLASS_TAG.put(cls, tag);
   1.438 -            CONSTANT_VALUE_CLASS[(byte)tag] = cls;
   1.439 -        }
   1.440 -    }
   1.441 -
   1.442 -    static Class<?> classForTag(byte tag) {
   1.443 -        if ((tag & 0xFF) >= CONSTANT_VALUE_CLASS.length)
   1.444 -            return null;
   1.445 -        return CONSTANT_VALUE_CLASS[tag];
   1.446 -    }
   1.447 -
   1.448 -    static byte tagForConstant(Class<?> cls) {
   1.449 -        Byte tag = CONSTANT_VALUE_CLASS_TAG.get(cls);
   1.450 -        return (tag == null) ? CONSTANT_None : (byte)tag;
   1.451 -    }
   1.452 -
   1.453 -    private static void checkClassName(String className) {
   1.454 -        if (className.indexOf('/') >= 0 || className.indexOf(';') >= 0)
   1.455 -            throw new IllegalArgumentException("invalid class name " + className);
   1.456 -    }
   1.457 -
   1.458 -    static String addSemis(String name, String... names) {
   1.459 -        StringBuilder buf = new StringBuilder(name.length() * 5);
   1.460 -        buf.append(name);
   1.461 -        for (String name2 : names) {
   1.462 -            buf.append(';').append(name2);
   1.463 -        }
   1.464 -        String res = buf.toString();
   1.465 -        assert(stripSemis(names.length, res)[0].equals(name));
   1.466 -        assert(stripSemis(names.length, res)[1].equals(names[0]));
   1.467 -        assert(names.length == 1 ||
   1.468 -               stripSemis(names.length, res)[2].equals(names[1]));
   1.469 -        return res;
   1.470 -    }
   1.471 -
   1.472 -    static String[] stripSemis(int count, String string) {
   1.473 -        String[] res = new String[count+1];
   1.474 -        int pos = 0;
   1.475 -        for (int i = 0; i < count; i++) {
   1.476 -            int pos2 = string.indexOf(';', pos);
   1.477 -            if (pos2 < 0)  pos2 = string.length();  // yuck
   1.478 -            res[i] = string.substring(pos, pos2);
   1.479 -            pos = pos2;
   1.480 -        }
   1.481 -        res[count] = string.substring(pos);
   1.482 -        return res;
   1.483 -    }
   1.484 -
   1.485 -    public String toString() {
   1.486 -        StringBuilder buf = new StringBuilder(this.getClass().getName());
   1.487 -        buf.append("{");
   1.488 -        Object[] origCP = null;
   1.489 -        for (int i = 0; i < patchArray.length; i++) {
   1.490 -            if (patchArray[i] == null)  continue;
   1.491 -            if (origCP != null) {
   1.492 -                buf.append(", ");
   1.493 -            } else {
   1.494 -                try {
   1.495 -                    origCP = getOriginalCP();
   1.496 -                } catch (InvalidConstantPoolFormatException ee) {
   1.497 -                    origCP = new Object[0];
   1.498 -                }
   1.499 -            }
   1.500 -            Object orig = (i < origCP.length) ? origCP[i] : "?";
   1.501 -            buf.append(orig).append("=").append(patchArray[i]);
   1.502 -        }
   1.503 -        buf.append("}");
   1.504 -        return buf.toString();
   1.505 -    }
   1.506 -}