diff a/test/lib/org/openjdk/asmtools/jdis/AnnotationElement.java b/test/lib/org/openjdk/asmtools/jdis/AnnotationElement.java
--- /dev/null
+++ b/test/lib/org/openjdk/asmtools/jdis/AnnotationElement.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.asmtools.jdis;
+
+import static java.lang.String.format;
+import static org.openjdk.asmtools.jasm.Tables.*;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Base class of all AnnotationElement entries
+ */
+public class AnnotationElement {
+
+    /**
+     *
+     * CPX_AnnotElem
+     *
+     * base class for an annotation value.
+     *
+     */
+    public static class AnnotValue {
+
+        /**
+         * tag the descriptor for the constant
+         */
+        public AnnotElemType tag;
+
+        // internal references
+        protected ClassData cls;
+
+        public AnnotValue(AnnotElemType tagval, ClassData cls) {
+            tag = tagval;
+            this.cls = cls;
+        }
+
+        public String stringVal() {
+            return "";
+        }
+
+        public void print(PrintWriter out, String tab) {
+            out.print(tag.val() + "  ");
+        }
+
+        @Override
+        public String toString() {
+            return "<AnnotValue " + tag.printval() + " " + stringVal() + ">";
+        }
+    }
+
+    /**
+     *
+     * CPX_AnnotElem
+     *
+     * Annotation value which is described by a single CPX entry (ie. String, byte, char,
+     * int, short, boolean, float, long, double, class reference).
+     *
+     */
+    public static class CPX_AnnotValue extends AnnotValue {
+
+        /**
+         * tag the descriptor for the constant
+         */
+        public int cpx;
+
+        public CPX_AnnotValue(AnnotElemType tag, ClassData cls, int cpx) {
+            super(tag, cls);
+            this.cpx = cpx;
+        }
+
+        @Override
+        public String stringVal() {
+            StringBuilder sb = new StringBuilder();
+            switch (tag) {
+                case AE_STRING:    // String
+                    sb.append('"' + cls.pool.getString(cpx) + '"');
+                    break;
+                case AE_BYTE:    // Byte
+                    sb.append("byte " + cls.pool.getConst(cpx).stringVal());
+                    break;
+                case AE_CHAR:    // Char
+                    sb.append("char " + cls.pool.getConst(cpx).stringVal());
+                    break;
+                case AE_INT:    // Int  (no need to add keyword)
+                    sb.append(cls.pool.getConst(cpx).stringVal());
+                    break;
+                case AE_SHORT:    // Short
+                    sb.append("short " + cls.pool.getConst(cpx).stringVal());
+                    break;
+                case AE_BOOLEAN:    // Boolean
+                    ConstantPool.CP_Int cns = (ConstantPool.CP_Int) cls.pool.getConst(cpx);
+                    sb.append("boolean " + (cns.value == 0 ? "false" : "true"));
+                    break;
+                case AE_FLOAT:    // Float
+                    sb.append(cls.pool.getConst(cpx).stringVal()); // + "f");
+                    break;
+                case AE_DOUBLE:    // Double
+                    sb.append(cls.pool.getConst(cpx).stringVal()); // + "d");
+                    break;
+                case AE_LONG:    // Long
+                    sb.append(cls.pool.getConst(cpx).stringVal()); // + "l");
+                    break;
+                case AE_CLASS:    // Class
+                    sb.append("class " + cls.pool.decodeClassDescriptor(cpx));
+                    break;
+                default:
+                    break;
+            }
+            return sb.toString();
+        }
+
+        @Override
+        public void print(PrintWriter out, String tab) {
+            out.print(tab + stringVal());
+        }
+
+        @Override
+        public String toString() {
+            return "<CPX_AnnotValue tag: '" + tag + "' stringVal=" + this.stringVal() + ">";
+        }
+    }
+
+    /**
+     *
+     * CPX_AnnotElem
+     *
+     * AnnotElements that contain 2 cpx indices (ie. enums).
+     *
+     */
+    public static class CPX2_AnnotValue extends AnnotValue {
+
+        /**
+         * tag the descriptor for the constant
+         */
+        public int cpx1;
+        public int cpx2;
+
+        public CPX2_AnnotValue(AnnotElemType tag, ClassData cls, int cpx1, int cpx2) {
+            super(tag, cls);
+            this.cpx1 = cpx1;
+            this.cpx2 = cpx2;
+        }
+
+        @Override
+        public String stringVal() {
+            StringBuilder sb = new StringBuilder();
+            switch (tag) {
+
+                case AE_ENUM:    // Enum
+                    // print the enum type and constant name
+                    sb.append("enum " + cls.pool.decodeClassDescriptor(cpx1)
+                            + " " + cls.pool.getName(cpx2));
+                    break;
+                default:
+                    break;
+            }
+            return sb.toString();
+        }
+
+        @Override
+        public void print(PrintWriter out, String tab) {
+            out.print(tab + stringVal());
+        }
+
+        @Override
+        public String toString() {
+            return "<CPX2_AnnotValue tag: '" + tag + "' stringVal=" + this.stringVal() + ">";
+        }
+    }
+
+    /**
+     *
+     * Array_AnnotElem
+     *
+     * Annotation value that is an array of annotation elements.
+     *
+     */
+    public static class Array_AnnotValue extends AnnotValue {
+
+        /**
+         * tag the descriptor for the constant
+         */
+        public ArrayList<AnnotValue> array = new ArrayList<>();
+
+        public Array_AnnotValue(AnnotElemType tagval, ClassData cls) {
+            super(tagval, cls);
+        }
+
+        @Override
+        public String stringVal() {
+            StringBuilder sb = new StringBuilder();
+            sb.append(super.stringVal() + " = ");
+            sb.append("{");
+            int i = 0;
+            int cnt = array.size();
+            for (AnnotValue arrayelem : array) {
+                sb.append(arrayelem.toString());
+                if (i < cnt - 1) {
+                    sb.append(",");
+                }
+            }
+            sb.append("}");
+            return sb.toString();
+        }
+
+        public void add(AnnotValue elem) {
+            array.add(elem);
+        }
+
+        @Override
+        public void print(PrintWriter out, String tab) {
+            out.println("{");
+            int i = 0;
+            int cnt = array.size();
+            for (AnnotValue arrayelem : array) {
+                arrayelem.print(out, tab + "  ");
+                if (i < cnt - 1) {
+                    out.println(",");
+                }
+                i += 1;
+            }
+            out.println("}");
+        }
+
+        @Override
+        public String toString() {
+            return "<Array_AnnotValue " + tag + " " + stringVal() + ">";
+        }
+    }
+
+    /**
+     *
+     * Annot_AnnotValue
+     *
+     * Annotation value that is a reference to an annotation.
+     *
+     */
+    public static class Annot_AnnotValue extends AnnotValue {
+
+        /**
+         * tag the descriptor for the constant
+         */
+        AnnotationData annot;
+
+        public Annot_AnnotValue(AnnotElemType tagval, ClassData cls, AnnotationData annot) {
+            super(tagval, cls);
+            this.annot = annot;
+        }
+
+        @Override
+        public String stringVal() {
+            return annot.toString();
+        }
+
+        @Override
+        public void print(PrintWriter out, String tab) {
+//            out.print(tag + "\t");
+            annot.print(out, tab);
+        }
+
+        @Override
+        public String toString() {
+            return "<Annot_AnnotValue " + tag + " " + stringVal() + ">";
+        }
+    }
+
+    /*========================================================*/
+    /* Factory Method */
+    /**
+     *
+     * read
+     *
+     * Static factory - creates Annotation Elements.
+     *
+     */
+    public static AnnotValue readValue(DataInputStream in, ClassData cls, boolean invisible) throws IOException {
+        AnnotValue val = null;
+        char tg = (char) in.readByte();
+        AnnotElemType tag = annotElemType(tg);
+
+        switch (tag) {
+            case AE_STRING:     // String
+            case AE_BYTE:       // Byte
+            case AE_CHAR:       // Char
+            case AE_INT:        // Int  (no need to add keyword)
+            case AE_SHORT:      // Short
+            case AE_BOOLEAN:    // Boolean
+            case AE_FLOAT:      // Float
+            case AE_DOUBLE:     // Double
+            case AE_LONG:       // Long
+            case AE_CLASS:      // Class
+                // CPX based Annotation
+                int CPX = in.readShort();
+                val = new CPX_AnnotValue(tag, cls, CPX);
+                break;
+            case AE_ENUM:    // Enum
+                // CPX2 based Annotation
+                int CPX1 = in.readShort();
+                int CPX2 = in.readShort();
+                val = new CPX2_AnnotValue(tag, cls, CPX1, CPX2);
+                break;
+            case AE_ANNOTATION:    // Annotation
+                AnnotationData ad = new AnnotationData(invisible, cls);
+                ad.read(in);
+                val = new Annot_AnnotValue(tag, cls, ad);
+                break;
+            case AE_ARRAY:    // Array
+                Array_AnnotValue aelem = new Array_AnnotValue(tag, cls);
+                val = aelem;
+                int cnt = in.readShort();
+                for (int i = 0; i < cnt; i++) {
+                    aelem.add(readValue(in, cls, invisible));
+                }
+                break;
+            default:
+                throw new IOException("Unknown tag in annotation '" + tg + "' [" + Integer.toHexString(tg) + "]");
+        }
+
+        return val;
+    }
+
+    /*========================================================*/
+
+    /*-------------------------------------------------------- */
+    /* AnnotElem Fields */
+    /**
+     * constant pool index for the name of the Annotation Element
+     */
+    public int name_cpx;
+
+    public AnnotValue value = null;
+
+    // internal references
+    protected ClassData cls;
+    /*-------------------------------------------------------- */
+
+    public AnnotationElement(ClassData cls) {
+        this.cls = cls;
+    }
+
+    /**
+     *
+     * read
+     *
+     * read and resolve the method data called from ClassData. precondition: NumFields has
+     * already been read from the stream.
+     *
+     */
+    public void read(DataInputStream in, boolean invisible) throws IOException {
+        name_cpx = in.readShort();
+        value = readValue(in, cls, invisible);
+        TraceUtils.traceln(format("                   AnnotElem: name[%d]=%s value=%s", name_cpx, cls.pool.getString(name_cpx), value.toString()));
+    }
+
+    public String stringVal() {
+        return cls.pool.getName(name_cpx);
+    }
+
+    public void print(PrintWriter out, String tab) {
+        out.print(stringVal() + " = ");
+        value.print(out, "");
+    }
+
+    @Override
+    public String toString() {
+        return "<AnnotElem " + stringVal() + " = " + value.toString() + ">";
+    }
+}
