45N/A/*
553N/A * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
45N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
45N/A *
45N/A * This code is free software; you can redistribute it and/or modify it
45N/A * under the terms of the GNU General Public License version 2 only, as
45N/A * published by the Free Software Foundation.
45N/A *
45N/A * This code is distributed in the hope that it will be useful, but WITHOUT
45N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
45N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
45N/A * version 2 for more details (a copy is included in the LICENSE file that
45N/A * accompanied this code).
45N/A *
45N/A * You should have received a copy of the GNU General Public License version
45N/A * 2 along with this work; if not, write to the Free Software Foundation,
45N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
45N/A *
553N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
553N/A * or visit www.oracle.com if you need additional information or have any
553N/A * questions.
45N/A */
45N/A
45N/A/*
45N/A * @test
45N/A * @bug 6622260
45N/A * @summary javap prints negative bytes incorrectly in hex
45N/A */
45N/A
45N/Aimport java.io.*;
45N/A
45N/Apublic class T6622260 {
45N/A public static void main(String[] args) throws Exception {
45N/A new T6622260().run();
45N/A }
45N/A
45N/A public void run() throws IOException {
45N/A File javaFile = writeTestFile();
45N/A File classFile = compileTestFile(javaFile);
45N/A modifyClassFile(classFile);
45N/A String output = javap(classFile);
45N/A verify(output);
45N/A }
45N/A
45N/A File writeTestFile() throws IOException {
45N/A File f = new File("Test.java");
45N/A PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
45N/A out.println("@Deprecated class Test { int f; void m() { } }");
45N/A out.close();
45N/A return f;
45N/A }
45N/A
45N/A File compileTestFile(File f) {
45N/A int rc = com.sun.tools.javac.Main.compile(new String[] { f.getPath() });
45N/A if (rc != 0)
45N/A throw new Error("compilation failed. rc=" + rc);
45N/A String path = f.getPath();
45N/A return new File(path.substring(0, path.length() - 5) + ".class");
45N/A }
45N/A
45N/A void modifyClassFile(File f) throws IOException {
45N/A String newAttributeName = "NonstandardAttribute";
45N/A byte[] newAttributeData = { 0, 1, 2, 127, (byte)128, (byte)129, (byte)254, (byte)255 };
45N/A
45N/A DataInputStream in = new DataInputStream(new FileInputStream(f));
45N/A byte[] data = new byte[(int) f.length()];
45N/A in.readFully(data);
45N/A in.close();
45N/A
45N/A in = new DataInputStream(new ByteArrayInputStream(data));
45N/A in.skipBytes(4); // magic
45N/A in.skipBytes(2); // minor
45N/A in.skipBytes(2); // minor
45N/A
45N/A int constantPoolPos = data.length - in.available();
45N/A int constant_pool_count = skipConstantPool(in);
45N/A
45N/A int flagsPos = data.length - in.available();
45N/A in.skipBytes(2); // access_flags
45N/A in.skipBytes(2); // this_class
45N/A in.skipBytes(2); // super_class
45N/A
45N/A int interfaces_count = in.readUnsignedShort();
45N/A in.skipBytes(interfaces_count * 2);
45N/A
45N/A int field_count = in.readUnsignedShort();
45N/A for (int i = 0; i < field_count; i++) {
45N/A in.skipBytes(6); // access_flags, name_index, descriptor_index
45N/A skipAttributes(in);
45N/A }
45N/A
45N/A int method_count = in.readUnsignedShort();
45N/A for (int i = 0; i < method_count; i++) {
45N/A in.skipBytes(6); // access_flags, name_index, descriptor_index
45N/A skipAttributes(in);
45N/A }
45N/A
45N/A int classAttributesPos = data.length - in.available();
45N/A int attributes_count = in.readUnsignedShort();
45N/A
45N/A f.renameTo(new File(f.getPath() + ".BAK"));
45N/A DataOutputStream out = new DataOutputStream(new FileOutputStream(f));
45N/A
45N/A // copy head
45N/A out.write(data, 0, constantPoolPos);
45N/A
45N/A // copy constant pool, adding in name of new attribute
45N/A out.writeShort(constant_pool_count + 1);
45N/A out.write(data, constantPoolPos + 2, flagsPos - constantPoolPos - 2);
45N/A out.write(1); // CONSTANT_Utf8
45N/A out.writeUTF(newAttributeName);
45N/A
45N/A // copy flags, class, superclass, interfaces, fields and methods
45N/A out.write(data, flagsPos, classAttributesPos - flagsPos);
45N/A
45N/A // copy class attributes, adding in new attribute
45N/A out.writeShort(attributes_count + 1);
45N/A out.write(data, classAttributesPos + 2, data.length - classAttributesPos - 2);
45N/A out.writeShort(constant_pool_count); // index of new attribute name
45N/A out.writeInt(newAttributeData.length);
45N/A out.write(newAttributeData);
45N/A out.close();
45N/A }
45N/A
45N/A int skipConstantPool(DataInputStream in) throws IOException {
45N/A int constant_pool_count = in.readUnsignedShort();
45N/A for (int i = 1; i < constant_pool_count; i++) {
45N/A int tag = in.readUnsignedByte();
45N/A switch (tag) {
45N/A case 1: // CONSTANT_Utf8
45N/A int length = in.readUnsignedShort();
45N/A in.skipBytes(length); // bytes
45N/A break;
45N/A
45N/A case 3: // CONSTANT_Integer
45N/A case 4: // CONSTANT_Float
45N/A in.skipBytes(4); // bytes
45N/A break;
45N/A
45N/A case 5: // CONSTANT_Long
45N/A case 6: // CONSTANT_Double
45N/A in.skipBytes(8); // high_bytes, low_bytes
45N/A break;
45N/A
45N/A case 7: // CONSTANT_Class
45N/A in.skipBytes(2); // name_index
45N/A break;
45N/A
45N/A case 8: // CONSTANT_String
45N/A in.skipBytes(2); // string_index
45N/A break;
45N/A
45N/A case 9: // CONSTANT_FieldRef
45N/A case 10: // CONSTANT_Methodref
45N/A case 11: // CONSTANT_InterfaceMethodref
45N/A in.skipBytes(4); // class_index, name_and_type_index
45N/A break;
45N/A
45N/A case 12: // CONSTANT_NameAndType
45N/A in.skipBytes(4); // name_index, descriptor_index
45N/A break;
45N/A
45N/A default:
45N/A throw new Error("constant pool tag: " + tag);
45N/A }
45N/A }
45N/A return constant_pool_count;
45N/A }
45N/A
45N/A int skipAttributes(DataInputStream in) throws IOException {
45N/A int attributes_count = in.readUnsignedShort();
45N/A for (int i = 0; i < attributes_count; i++) {
45N/A in.skipBytes(2); // attribute_name_index;
45N/A int length = in.readInt();
45N/A in.skipBytes(length); // info
45N/A }
45N/A return attributes_count;
45N/A }
45N/A
45N/A String javap(File f) {
45N/A StringWriter sw = new StringWriter();
45N/A PrintWriter out = new PrintWriter(sw);
45N/A int rc = com.sun.tools.javap.Main.run(new String[] { "-v", f.getPath() }, out);
45N/A if (rc != 0)
45N/A throw new Error("javap failed. rc=" + rc);
45N/A out.close();
45N/A return sw.toString();
45N/A }
45N/A
45N/A void verify(String output) {
45N/A System.out.println(output);
145N/A output = output.substring(output.indexOf("Test.java"));
45N/A if (output.indexOf("-") >= 0)
45N/A throw new Error("- found in output");
45N/A if (output.indexOf("FFFFFF") >= 0)
45N/A throw new Error("FFFFFF found in output");
45N/A }
45N/A}