langtools/test/tools/javap/T6622260.java
changeset 727 cb50c1ae7bab
child 1039 ca7b8a8c9268
equal deleted inserted replaced
661:9b2f1fe5c183 727:cb50c1ae7bab
       
     1 /*
       
     2  * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    21  * have any questions.
       
    22  */
       
    23 
       
    24 /*
       
    25  * @test
       
    26  * @bug 6622260
       
    27  * @summary javap prints negative bytes incorrectly in hex
       
    28  */
       
    29 
       
    30 import java.io.*;
       
    31 
       
    32 public class T6622260 {
       
    33     public static void main(String[] args) throws Exception {
       
    34         new T6622260().run();
       
    35     }
       
    36 
       
    37     public void run() throws IOException {
       
    38         File javaFile = writeTestFile();
       
    39         File classFile = compileTestFile(javaFile);
       
    40         modifyClassFile(classFile);
       
    41         String output = javap(classFile);
       
    42         verify(output);
       
    43     }
       
    44 
       
    45     File writeTestFile() throws IOException {
       
    46         File f = new File("Test.java");
       
    47         PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
       
    48         out.println("@Deprecated class Test { int f; void m() { } }");
       
    49         out.close();
       
    50         return f;
       
    51     }
       
    52 
       
    53     File compileTestFile(File f) {
       
    54         int rc = com.sun.tools.javac.Main.compile(new String[] { f.getPath() });
       
    55         if (rc != 0)
       
    56             throw new Error("compilation failed. rc=" + rc);
       
    57         String path = f.getPath();
       
    58         return new File(path.substring(0, path.length() - 5) + ".class");
       
    59     }
       
    60 
       
    61     void modifyClassFile(File f) throws IOException {
       
    62         String newAttributeName = "NonstandardAttribute";
       
    63         byte[] newAttributeData = { 0, 1, 2, 127, (byte)128, (byte)129, (byte)254, (byte)255 };
       
    64 
       
    65         DataInputStream in = new DataInputStream(new FileInputStream(f));
       
    66         byte[] data = new byte[(int) f.length()];
       
    67         in.readFully(data);
       
    68         in.close();
       
    69 
       
    70         in = new DataInputStream(new ByteArrayInputStream(data));
       
    71         in.skipBytes(4); // magic
       
    72         in.skipBytes(2); // minor
       
    73         in.skipBytes(2); // minor
       
    74 
       
    75         int constantPoolPos = data.length - in.available();
       
    76         int constant_pool_count = skipConstantPool(in);
       
    77 
       
    78         int flagsPos = data.length - in.available();
       
    79         in.skipBytes(2); // access_flags
       
    80         in.skipBytes(2); // this_class
       
    81         in.skipBytes(2); // super_class
       
    82 
       
    83         int interfaces_count = in.readUnsignedShort();
       
    84         in.skipBytes(interfaces_count * 2);
       
    85 
       
    86         int field_count = in.readUnsignedShort();
       
    87         for (int i = 0; i < field_count; i++) {
       
    88             in.skipBytes(6); // access_flags, name_index, descriptor_index
       
    89             skipAttributes(in);
       
    90         }
       
    91 
       
    92         int method_count = in.readUnsignedShort();
       
    93         for (int i = 0; i < method_count; i++) {
       
    94             in.skipBytes(6); // access_flags, name_index, descriptor_index
       
    95             skipAttributes(in);
       
    96         }
       
    97 
       
    98         int classAttributesPos = data.length - in.available();
       
    99         int attributes_count = in.readUnsignedShort();
       
   100 
       
   101         f.renameTo(new File(f.getPath() + ".BAK"));
       
   102         DataOutputStream out = new DataOutputStream(new FileOutputStream(f));
       
   103 
       
   104         // copy head
       
   105         out.write(data, 0, constantPoolPos);
       
   106 
       
   107         // copy constant pool, adding in name of new attribute
       
   108         out.writeShort(constant_pool_count + 1);
       
   109         out.write(data, constantPoolPos + 2, flagsPos - constantPoolPos - 2);
       
   110         out.write(1); // CONSTANT_Utf8
       
   111         out.writeUTF(newAttributeName);
       
   112 
       
   113         // copy flags, class, superclass, interfaces, fields and methods
       
   114         out.write(data, flagsPos, classAttributesPos - flagsPos);
       
   115 
       
   116         // copy class attributes, adding in new attribute
       
   117         out.writeShort(attributes_count + 1);
       
   118         out.write(data, classAttributesPos + 2, data.length - classAttributesPos - 2);
       
   119         out.writeShort(constant_pool_count); // index of new attribute name
       
   120         out.writeInt(newAttributeData.length);
       
   121         out.write(newAttributeData);
       
   122         out.close();
       
   123     }
       
   124 
       
   125     int skipConstantPool(DataInputStream in) throws IOException {
       
   126         int constant_pool_count = in.readUnsignedShort();
       
   127         for (int i = 1; i < constant_pool_count; i++) {
       
   128             int tag = in.readUnsignedByte();
       
   129             switch (tag) {
       
   130             case  1: // CONSTANT_Utf8
       
   131                 int length = in.readUnsignedShort();
       
   132                 in.skipBytes(length); // bytes
       
   133                 break;
       
   134 
       
   135             case  3: // CONSTANT_Integer
       
   136             case  4: // CONSTANT_Float
       
   137                 in.skipBytes(4); // bytes
       
   138                 break;
       
   139 
       
   140             case  5: // CONSTANT_Long
       
   141             case  6: // CONSTANT_Double
       
   142                 in.skipBytes(8); // high_bytes, low_bytes
       
   143                 break;
       
   144 
       
   145             case  7: // CONSTANT_Class
       
   146                 in.skipBytes(2); // name_index
       
   147                 break;
       
   148 
       
   149             case  8: // CONSTANT_String
       
   150                 in.skipBytes(2); // string_index
       
   151                 break;
       
   152 
       
   153             case  9: // CONSTANT_FieldRef
       
   154             case 10: // CONSTANT_Methodref
       
   155             case 11: // CONSTANT_InterfaceMethodref
       
   156                 in.skipBytes(4); // class_index, name_and_type_index
       
   157                 break;
       
   158 
       
   159             case 12: // CONSTANT_NameAndType
       
   160                 in.skipBytes(4); // name_index, descriptor_index
       
   161                 break;
       
   162 
       
   163             default:
       
   164                 throw new Error("constant pool tag: " + tag);
       
   165             }
       
   166         }
       
   167         return constant_pool_count;
       
   168     }
       
   169 
       
   170     int skipAttributes(DataInputStream in) throws IOException {
       
   171         int attributes_count = in.readUnsignedShort();
       
   172         for (int i = 0; i < attributes_count; i++) {
       
   173             in.skipBytes(2); // attribute_name_index;
       
   174             int length = in.readInt();
       
   175             in.skipBytes(length); // info
       
   176         }
       
   177         return attributes_count;
       
   178     }
       
   179 
       
   180     String javap(File f) {
       
   181         StringWriter sw = new StringWriter();
       
   182         PrintWriter out = new PrintWriter(sw);
       
   183         int rc = com.sun.tools.javap.Main.run(new String[] { "-v", f.getPath() }, out);
       
   184         if (rc != 0)
       
   185             throw new Error("javap failed. rc=" + rc);
       
   186         out.close();
       
   187         return sw.toString();
       
   188     }
       
   189 
       
   190     void verify(String output) {
       
   191         System.out.println(output);
       
   192         if (output.indexOf("-") >= 0)
       
   193             throw new Error("- found in output");
       
   194         if (output.indexOf("FFFFFF") >= 0)
       
   195             throw new Error("FFFFFF found in output");
       
   196     }
       
   197 }