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