6866657: add byteLength method to primary classfile types
authorjjg
Thu, 30 Jul 2009 07:48:24 -0700
changeset 3543 58b72b096bcb
parent 3542 3fdb9f291a7e
child 3544 c6d0f086397f
6866657: add byteLength method to primary classfile types Reviewed-by: mchung
langtools/src/share/classes/com/sun/tools/classfile/AccessFlags.java
langtools/src/share/classes/com/sun/tools/classfile/Attribute.java
langtools/src/share/classes/com/sun/tools/classfile/Attributes.java
langtools/src/share/classes/com/sun/tools/classfile/ClassFile.java
langtools/src/share/classes/com/sun/tools/classfile/ConstantPool.java
langtools/src/share/classes/com/sun/tools/classfile/Field.java
langtools/src/share/classes/com/sun/tools/classfile/Method.java
langtools/test/tools/javap/T6866657.java
--- a/langtools/src/share/classes/com/sun/tools/classfile/AccessFlags.java	Thu Jul 30 10:30:34 2009 +0100
+++ b/langtools/src/share/classes/com/sun/tools/classfile/AccessFlags.java	Thu Jul 30 07:48:24 2009 -0700
@@ -76,6 +76,10 @@
         return (flags & mask) != 0;
     }
 
+    public int byteLength() {
+        return 2;
+    }
+
     private static final int[] classModifiers = {
         ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT, ACC_MODULE
     };
--- a/langtools/src/share/classes/com/sun/tools/classfile/Attribute.java	Thu Jul 30 10:30:34 2009 +0100
+++ b/langtools/src/share/classes/com/sun/tools/classfile/Attribute.java	Thu Jul 30 07:48:24 2009 -0700
@@ -166,6 +166,10 @@
 
     public abstract <R,D> R accept(Attribute.Visitor<R,D> visitor, D data);
 
+    public int byteLength() {
+        return 6 + attribute_length;
+    }
+
     public final int attribute_name_index;
     public final int attribute_length;
 
--- a/langtools/src/share/classes/com/sun/tools/classfile/Attributes.java	Thu Jul 30 10:30:34 2009 +0100
+++ b/langtools/src/share/classes/com/sun/tools/classfile/Attributes.java	Thu Jul 30 07:48:24 2009 -0700
@@ -95,6 +95,13 @@
         return attrs.length;
     }
 
+    public int byteLength() {
+        int length = 2;
+        for (Attribute a: attrs)
+            length += a.byteLength();
+        return length;
+    }
+
     public final Attribute[] attrs;
     public final Map<String, Attribute> map;
 }
--- a/langtools/src/share/classes/com/sun/tools/classfile/ClassFile.java	Thu Jul 30 10:30:34 2009 +0100
+++ b/langtools/src/share/classes/com/sun/tools/classfile/ClassFile.java	Thu Jul 30 07:48:24 2009 -0700
@@ -139,6 +139,38 @@
         return access_flags.is(ACC_INTERFACE);
     }
 
+    public int byteLength() {
+        return  4 +     // magic
+                2 +     // minor
+                2 +     // major
+                constant_pool.byteLength() +
+                2 +     // access flags
+                2 +     // this_class
+                2 +     // super_class
+                byteLength(interfaces) +
+                byteLength(fields) +
+                byteLength(methods) +
+                attributes.byteLength();
+    }
+
+    private int byteLength(int[] indices) {
+        return 2 + 2 * indices.length;
+    }
+
+    private int byteLength(Field[] fields) {
+        int length = 2;
+        for (Field f: fields)
+            length += f.byteLength();
+        return length;
+    }
+
+    private int byteLength(Method[] methods) {
+        int length = 2;
+        for (Method m: methods)
+            length += m.byteLength();
+        return length;
+    }
+
     public final int magic;
     public final int minor_version;
     public final int major_version;
--- a/langtools/src/share/classes/com/sun/tools/classfile/ConstantPool.java	Thu Jul 30 10:30:34 2009 +0100
+++ b/langtools/src/share/classes/com/sun/tools/classfile/ConstantPool.java	Thu Jul 30 07:48:24 2009 -0700
@@ -25,7 +25,9 @@
 
 package com.sun.tools.classfile;
 
+import java.io.DataOutputStream;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.util.Iterator;
 
 /**
@@ -179,6 +181,16 @@
         return pool.length;
     }
 
+    public int byteLength() {
+        int length = 2;
+        for (int i = 1; i < size(); ) {
+            CPInfo cpInfo = pool[i];
+            length += cpInfo.byteLength();
+            i += cpInfo.size();
+        }
+        return length;
+    }
+
     public CPInfo get(int index) throws InvalidIndex {
         if (index <= 0 || index >= pool.length)
             throw new InvalidIndex(index);
@@ -291,6 +303,8 @@
             return 1;
         }
 
+        public abstract int byteLength();
+
         public abstract <R,D> R accept(Visitor<R,D> visitor, D data);
 
         protected final ConstantPool cp;
@@ -315,6 +329,10 @@
             return tag;
         }
 
+        public int byteLength() {
+            return 5;
+        }
+
         public CONSTANT_Class_info getClassInfo() throws ConstantPoolException {
             return cp.getClassInfo(class_index);
         }
@@ -347,6 +365,10 @@
             return CONSTANT_Class;
         }
 
+        public int  byteLength() {
+            return 3;
+        }
+
         public String getName() throws ConstantPoolException {
             return cp.getUTF8Value(name_index);
         }
@@ -390,6 +412,10 @@
             return CONSTANT_Double;
         }
 
+        public int  byteLength() {
+            return 9;
+        }
+
         @Override
         public int size() {
             return 2;
@@ -439,6 +465,10 @@
             return CONSTANT_Float;
         }
 
+        public int byteLength() {
+            return 5;
+        }
+
         @Override
         public String toString() {
             return "CONSTANT_Float_info[value: " + value + "]";
@@ -464,6 +494,10 @@
             return CONSTANT_Integer;
         }
 
+        public int byteLength() {
+            return 5;
+        }
+
         @Override
         public String toString() {
             return "CONSTANT_Integer_info[value: " + value + "]";
@@ -513,6 +547,10 @@
             return 2;
         }
 
+        public int byteLength() {
+            return 9;
+        }
+
         @Override
         public String toString() {
             return "CONSTANT_Long_info[value: " + value + "]";
@@ -561,6 +599,10 @@
             return CONSTANT_NameAndType;
         }
 
+        public int byteLength() {
+            return 5;
+        }
+
         public String getName() throws ConstantPoolException {
             return cp.getUTF8Value(name_index);
         }
@@ -597,6 +639,10 @@
             return CONSTANT_String;
         }
 
+        public int byteLength() {
+            return 3;
+        }
+
         public String getString() throws ConstantPoolException {
             return cp.getUTF8Value(string_index);
         }
@@ -626,6 +672,20 @@
             return CONSTANT_Utf8;
         }
 
+        public int byteLength() {
+            class SizeOutputStream extends OutputStream {
+                @Override
+                public void write(int b) throws IOException {
+                    size++;
+                }
+                int size;
+            }
+            SizeOutputStream sizeOut = new SizeOutputStream();
+            DataOutputStream out = new DataOutputStream(sizeOut);
+            try { out.writeUTF(value); } catch (IOException ignore) { }
+            return 1 + sizeOut.size;
+        }
+
         @Override
         public String toString() {
             if (value.length() < 32 && isPrintableAscii(value))
--- a/langtools/src/share/classes/com/sun/tools/classfile/Field.java	Thu Jul 30 10:30:34 2009 +0100
+++ b/langtools/src/share/classes/com/sun/tools/classfile/Field.java	Thu Jul 30 07:48:24 2009 -0700
@@ -50,6 +50,10 @@
         this.attributes = attributes;
     }
 
+    public int byteLength() {
+        return 6 + attributes.byteLength();
+    }
+
     public String getName(ConstantPool constant_pool) throws ConstantPoolException {
         return constant_pool.getUTF8Value(name_index);
     }
--- a/langtools/src/share/classes/com/sun/tools/classfile/Method.java	Thu Jul 30 10:30:34 2009 +0100
+++ b/langtools/src/share/classes/com/sun/tools/classfile/Method.java	Thu Jul 30 07:48:24 2009 -0700
@@ -50,6 +50,10 @@
         this.attributes = attributes;
     }
 
+    public int byteLength() {
+        return 6 + attributes.byteLength();
+    }
+
     public String getName(ConstantPool constant_pool) throws ConstantPoolException {
         return constant_pool.getUTF8Value(name_index);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javap/T6866657.java	Thu Jul 30 07:48:24 2009 -0700
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+/*
+ * @test
+ * @bug 6866657
+ * @summary add byteLength() method to primary classfile types
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.tools.*;
+import com.sun.tools.javap.*;
+
+public class T6866657
+{
+    public static void main(String... args) {
+        new T6866657().run();
+    }
+
+    void run() {
+        verify("java.lang.Object");
+        verify("java.lang.String");
+        verify("java.util.List");
+        verify("java.util.ArrayList");
+        if (errors > 0)
+            throw new Error(errors + " found.");
+    }
+
+    void verify(String className) {
+        try {
+            PrintWriter log = new PrintWriter(System.out);
+            JavaFileManager fileManager = JavapFileManager.create(null, log);
+            JavaFileObject fo = fileManager.getJavaFileForInput(StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);
+            if (fo == null) {
+                error("Can't find " + className);
+            } else {
+                JavapTask t = new JavapTask(log, fileManager, null);
+                t.handleOptions(new String[] { "-sysinfo", className });
+                JavapTask.ClassFileInfo cfInfo = t.read(fo);
+                expectEqual(cfInfo.cf.byteLength(), cfInfo.size);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            error("Exception: " + e);
+        }
+    }
+
+    void expectEqual(int found, int expected) {
+        if (found != expected)
+            error("bad value found: " + found + " expected: " + expected);
+    }
+
+    void error(String msg) {
+        System.err.println(msg);
+        errors++;
+    }
+
+    int errors;
+}
+