T6622260.java revision 45:7708bd6d800d
1184870Syongari/*
2184870Syongari * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
3184870Syongari * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4184870Syongari *
5184870Syongari * This code is free software; you can redistribute it and/or modify it
6184870Syongari * under the terms of the GNU General Public License version 2 only, as
7184870Syongari * published by the Free Software Foundation.
8184870Syongari *
9184870Syongari * This code is distributed in the hope that it will be useful, but WITHOUT
10184870Syongari * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11184870Syongari * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12184870Syongari * version 2 for more details (a copy is included in the LICENSE file that
13184870Syongari * accompanied this code).
14184870Syongari *
15184870Syongari * You should have received a copy of the GNU General Public License version
16184870Syongari * 2 along with this work; if not, write to the Free Software Foundation,
17184870Syongari * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18184870Syongari *
19184870Syongari * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20184870Syongari * CA 95054 USA or visit www.sun.com if you need additional information or
21184870Syongari * have any questions.
22184870Syongari */
23184870Syongari
24184870Syongari/*
25184870Syongari * @test
26184870Syongari * @bug 6622260
27184870Syongari * @summary javap prints negative bytes incorrectly in hex
28184870Syongari */
29184870Syongari
30184870Syongariimport java.io.*;
31184870Syongari
32184870Syongaripublic class T6622260 {
33184870Syongari    public static void main(String[] args) throws Exception {
34184870Syongari        new T6622260().run();
35184870Syongari    }
36184870Syongari
37184870Syongari    public void run() throws IOException {
38184870Syongari        File javaFile = writeTestFile();
39184870Syongari        File classFile = compileTestFile(javaFile);
40184870Syongari        modifyClassFile(classFile);
41184870Syongari        String output = javap(classFile);
42184870Syongari        verify(output);
43184870Syongari    }
44184870Syongari
45184870Syongari    File writeTestFile() throws IOException {
46184870Syongari        File f = new File("Test.java");
47184870Syongari        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
48184870Syongari        out.println("@Deprecated class Test { int f; void m() { } }");
49184870Syongari        out.close();
50184870Syongari        return f;
51184870Syongari    }
52184870Syongari
53184870Syongari    File compileTestFile(File f) {
54184870Syongari        int rc = com.sun.tools.javac.Main.compile(new String[] { f.getPath() });
55184870Syongari        if (rc != 0)
56184870Syongari            throw new Error("compilation failed. rc=" + rc);
57184870Syongari        String path = f.getPath();
58184870Syongari        return new File(path.substring(0, path.length() - 5) + ".class");
59184870Syongari    }
60184870Syongari
61184870Syongari    void modifyClassFile(File f) throws IOException {
62184870Syongari        String newAttributeName = "NonstandardAttribute";
63184870Syongari        byte[] newAttributeData = { 0, 1, 2, 127, (byte)128, (byte)129, (byte)254, (byte)255 };
64184870Syongari
65184870Syongari        DataInputStream in = new DataInputStream(new FileInputStream(f));
66184870Syongari        byte[] data = new byte[(int) f.length()];
67184870Syongari        in.readFully(data);
68184870Syongari        in.close();
69184870Syongari
70184870Syongari        in = new DataInputStream(new ByteArrayInputStream(data));
71184870Syongari        in.skipBytes(4); // magic
72184870Syongari        in.skipBytes(2); // minor
73184870Syongari        in.skipBytes(2); // minor
74184870Syongari
75184870Syongari        int constantPoolPos = data.length - in.available();
76184870Syongari        int constant_pool_count = skipConstantPool(in);
77184870Syongari
78184870Syongari        int flagsPos = data.length - in.available();
79184870Syongari        in.skipBytes(2); // access_flags
80184870Syongari        in.skipBytes(2); // this_class
81184870Syongari        in.skipBytes(2); // super_class
82184870Syongari
83184870Syongari        int interfaces_count = in.readUnsignedShort();
84184870Syongari        in.skipBytes(interfaces_count * 2);
85184870Syongari
86184870Syongari        int field_count = in.readUnsignedShort();
87184870Syongari        for (int i = 0; i < field_count; i++) {
88184870Syongari            in.skipBytes(6); // access_flags, name_index, descriptor_index
89184870Syongari            skipAttributes(in);
90184870Syongari        }
91184870Syongari
92184870Syongari        int method_count = in.readUnsignedShort();
93184870Syongari        for (int i = 0; i < method_count; i++) {
94184870Syongari            in.skipBytes(6); // access_flags, name_index, descriptor_index
95184870Syongari            skipAttributes(in);
96184870Syongari        }
97184870Syongari
98184870Syongari        int classAttributesPos = data.length - in.available();
99184870Syongari        int attributes_count = in.readUnsignedShort();
100184870Syongari
101184870Syongari        f.renameTo(new File(f.getPath() + ".BAK"));
102184870Syongari        DataOutputStream out = new DataOutputStream(new FileOutputStream(f));
103184870Syongari
104184870Syongari        // copy head
105184870Syongari        out.write(data, 0, constantPoolPos);
106184870Syongari
107184870Syongari        // copy constant pool, adding in name of new attribute
108184870Syongari        out.writeShort(constant_pool_count + 1);
109184870Syongari        out.write(data, constantPoolPos + 2, flagsPos - constantPoolPos - 2);
110184870Syongari        out.write(1); // CONSTANT_Utf8
111184870Syongari        out.writeUTF(newAttributeName);
112184870Syongari
113184870Syongari        // copy flags, class, superclass, interfaces, fields and methods
114184870Syongari        out.write(data, flagsPos, classAttributesPos - flagsPos);
115184870Syongari
116184870Syongari        // copy class attributes, adding in new attribute
117184870Syongari        out.writeShort(attributes_count + 1);
118184870Syongari        out.write(data, classAttributesPos + 2, data.length - classAttributesPos - 2);
119184870Syongari        out.writeShort(constant_pool_count); // index of new attribute name
120184870Syongari        out.writeInt(newAttributeData.length);
121184870Syongari        out.write(newAttributeData);
122184870Syongari        out.close();
123184870Syongari    }
124184870Syongari
125184870Syongari    int skipConstantPool(DataInputStream in) throws IOException {
126184870Syongari        int constant_pool_count = in.readUnsignedShort();
127184870Syongari        for (int i = 1; i < constant_pool_count; i++) {
128184870Syongari            int tag = in.readUnsignedByte();
129184870Syongari            switch (tag) {
130184870Syongari            case  1: // CONSTANT_Utf8
131184870Syongari                int length = in.readUnsignedShort();
132184870Syongari                in.skipBytes(length); // bytes
133184870Syongari                break;
134184870Syongari
135184870Syongari            case  3: // CONSTANT_Integer
136184870Syongari            case  4: // CONSTANT_Float
137184870Syongari                in.skipBytes(4); // bytes
138184870Syongari                break;
139184870Syongari
140184870Syongari            case  5: // CONSTANT_Long
141184870Syongari            case  6: // CONSTANT_Double
142184870Syongari                in.skipBytes(8); // high_bytes, low_bytes
143184870Syongari                break;
144184870Syongari
145184870Syongari            case  7: // CONSTANT_Class
146184870Syongari                in.skipBytes(2); // name_index
147184870Syongari                break;
148184870Syongari
149184870Syongari            case  8: // CONSTANT_String
150184870Syongari                in.skipBytes(2); // string_index
151184870Syongari                break;
152184870Syongari
153184870Syongari            case  9: // CONSTANT_FieldRef
154184870Syongari            case 10: // CONSTANT_Methodref
155184870Syongari            case 11: // CONSTANT_InterfaceMethodref
156184870Syongari                in.skipBytes(4); // class_index, name_and_type_index
157184870Syongari                break;
158184870Syongari
159184870Syongari            case 12: // CONSTANT_NameAndType
160184870Syongari                in.skipBytes(4); // name_index, descriptor_index
161184870Syongari                break;
162184870Syongari
163184870Syongari            default:
164184870Syongari                throw new Error("constant pool tag: " + tag);
165184870Syongari            }
166184870Syongari        }
167184870Syongari        return constant_pool_count;
168184870Syongari    }
169184870Syongari
170184870Syongari    int skipAttributes(DataInputStream in) throws IOException {
171184870Syongari        int attributes_count = in.readUnsignedShort();
172184870Syongari        for (int i = 0; i < attributes_count; i++) {
173184870Syongari            in.skipBytes(2); // attribute_name_index;
174184870Syongari            int length = in.readInt();
175184870Syongari            in.skipBytes(length); // info
176184870Syongari        }
177184870Syongari        return attributes_count;
178184870Syongari    }
179184870Syongari
180184870Syongari    String javap(File f) {
181184870Syongari        StringWriter sw = new StringWriter();
182184870Syongari        PrintWriter out = new PrintWriter(sw);
183184870Syongari        int rc = com.sun.tools.javap.Main.run(new String[] { "-v", f.getPath() }, out);
184184870Syongari        if (rc != 0)
185184870Syongari            throw new Error("javap failed. rc=" + rc);
186184870Syongari        out.close();
187184870Syongari        return sw.toString();
188184870Syongari    }
189184870Syongari
190184870Syongari    void verify(String output) {
191184870Syongari        System.out.println(output);
192184870Syongari        if (output.indexOf("-") >= 0)
193184870Syongari            throw new Error("- found in output");
194184870Syongari        if (output.indexOf("FFFFFF") >= 0)
195184870Syongari            throw new Error("FFFFFF found in output");
196184870Syongari    }
197184870Syongari}
198184870Syongari