1eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin/** 2eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin * Copyright 2006-2017 the original author or authors. 3eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin * 4eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License"); 5eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin * you may not use this file except in compliance with the License. 6eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin * You may obtain a copy of the License at 7eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin * 8eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0 9eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin * 10eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin * Unless required by applicable law or agreed to in writing, software 11eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS, 12eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin * See the License for the specific language governing permissions and 14eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin * limitations under the License. 15eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin */ 16eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffinpackage org.objenesis; 17eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 18eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffinimport java.io.DataInputStream; 19eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffinimport java.io.FileInputStream; 20eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffinimport java.io.IOException; 21eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffinimport java.io.InputStream; 22eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffinimport java.util.Arrays; 23eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 24eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffinimport static org.junit.Assert.*; 25eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffinimport static org.objenesis.instantiator.basic.ClassDefinitionUtils.*; 26eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 27eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin/** 28eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin * @author Henri Tremblay 29eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin */ 30eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffinpublic class ClassReader { 31eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 32eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin byte[] buffer = new byte[256]; 33eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin Object[] constant_pool; 34eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 35eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public static void main(String[] args) throws IOException { 36eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin if(args.length != 1) { 37eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.println("Usage: ClassReader (path_to_the_class_file|class:complete_class_name)"); 38eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 39eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 40eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin ClassReader reader = new ClassReader(); 41eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin reader.readClass(args[0]); 42eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 43eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 44eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin static class CONSTANT_Utf8_info { 45eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin // int length; u2 is read by readUTF 46eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin String bytes; 47eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 48eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin CONSTANT_Utf8_info(DataInputStream in) throws IOException { 49eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin bytes = in.readUTF(); 50eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 51eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 52eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin @Override 53eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public String toString() { 54eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin return "CONSTANT_Utf8_info{" + 55eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin "bytes='" + bytes + '\'' + 56eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin '}'; 57eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 58eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 59eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 60eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin static class CONSTANT_Methodref_info { 61eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int class_index; // u2 62eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int name_and_type_index; // u2 63eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 64eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin CONSTANT_Methodref_info(DataInputStream in) throws IOException { 65eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin class_index = in.readUnsignedShort(); 66eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin name_and_type_index = in.readUnsignedShort(); 67eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 68eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 69eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin @Override 70eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public String toString() { 71eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin return "CONSTANT_Methodref_info{" + 72eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin "class_index=" + class_index + 73eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin ", name_and_type_index=" + name_and_type_index + 74eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin '}'; 75eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 76eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 77eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 78eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin static class CONSTANT_Class_info { 79eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int name_index; // u2 80eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 81eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public CONSTANT_Class_info(DataInputStream in) throws IOException{ 82eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin name_index = in.readUnsignedShort(); 83eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 84eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 85eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin @Override 86eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public String toString() { 87eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin return "CONSTANT_Class_info{" + 88eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin "name_index=" + name_index + 89eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin '}'; 90eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 91eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 92eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 93eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin static class CONSTANT_NameAndType_info { 94eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int name_index; // u2 95eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int descriptor_index; // u2 96eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 97eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public CONSTANT_NameAndType_info(DataInputStream in) throws IOException{ 98eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin name_index = in.readUnsignedShort(); 99eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin descriptor_index = in.readUnsignedShort(); 100eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 101eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 102eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin @Override 103eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public String toString() { 104eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin return "CONSTANT_NameAndType_info{" + 105eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin "name_index=" + name_index + 106eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin ", descriptor_index=" + descriptor_index + 107eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin '}'; 108eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 109eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 110eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 111eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin class method_info { 112eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int access_flags; // u2 113eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int name_index; 114eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int descriptor_index; 115eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int attributes_count; 116eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin attribute_info[] attributes; 117eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 118eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public method_info(DataInputStream in) throws IOException{ 119eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin access_flags = in.readUnsignedShort(); 120eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin name_index = in.readUnsignedShort(); 121eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin descriptor_index = in.readUnsignedShort(); 122eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin attributes_count = in.readUnsignedShort(); 123eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin attributes = new attribute_info[attributes_count]; 124eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 125eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin for (int i = 0; i < attributes_count; i++) { 126eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin attributes[i] = new attribute_info(in); 127eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 128eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 129eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 130eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin @Override 131eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public String toString() { 132eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin return "method_info{" + 133eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin "access_flags=" + access_flags + 134eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin ", name_index=" + name_index + 135eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin ", descriptor_index=" + descriptor_index + 136eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin ", attributes_count=" + attributes_count + 137eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin '}'; 138eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 139eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 140eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 141eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin class attribute_info { 142eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int attribute_name_index; // u2 143eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int attribute_length; // u4 144eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin Object info; 145eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 146eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public attribute_info(DataInputStream in) throws IOException{ 147eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin attribute_name_index = in.readUnsignedShort(); 148eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin attribute_length = in.readInt(); 149eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 150eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin String attribute_name = ((CONSTANT_Utf8_info) constant_pool[attribute_name_index]).bytes; 151eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 152eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.println(this + " " + attribute_name); 153eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 154eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin if("Code".equals(attribute_name)) { 155eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin info = new Code_attribute(in); 156eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 157eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin else if("SourceFile".equals(attribute_name)) { 158eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin assertEquals(2, attribute_length); // always 2 159eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin info = new SourceFile_attribute(in); 160eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 161eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin else if("LineNumberTable".equals(attribute_name)) { 162eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin // I don't care about that (only used for debugging) so I will skip 163eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.println("Attribute LineNumberTable skipped"); 164eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin in.read(buffer, 0, attribute_length); 165eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 166eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin else if("LocalVariableTable".equals(attribute_name)) { 167eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin // I don't care about that (only used for debugging) so I will skip 168eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.println("Attribute LocalVariableTable skipped"); 169eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin in.read(buffer, 0, attribute_length); 170eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 171eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin else { 172eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin fail("Unknown attribute: " + attribute_name); 173eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 174eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 175eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.println("\t" + info); 176eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 177eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 178eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin @Override 179eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public String toString() { 180eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin return "attribute_info{" + 181eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin "attribute_name_index=" + attribute_name_index + 182eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin ", attribute_length=" + attribute_length + 183eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin '}'; 184eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 185eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 186eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 187eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin class Code_attribute { 188eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int max_stack; // u2 189eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int max_locals; // u2 190eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int code_length; // u4 191eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin byte[] code; // length of code_length 192eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int exception_table_length; // u2 if will be 0, so we will skip the exception_table 193eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int attributes_count; // u2 194eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin attribute_info[] attributes; 195eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 196eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin Code_attribute(DataInputStream in) throws IOException { 197eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin max_stack = in.readUnsignedShort(); 198eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin max_locals = in.readUnsignedShort(); 199eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin code_length = in.readInt(); 200eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin code = new byte[code_length]; 201eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin in.read(code); 202eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin exception_table_length = in.readUnsignedShort(); 203eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin attributes_count = in.readUnsignedShort(); 204eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin attributes = new attribute_info[attributes_count]; 205eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin for (int i = 0; i < attributes_count; i++) { 206eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin attributes[i] = new attribute_info(in); 207eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 208eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 209eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 210eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin @Override 211eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public String toString() { 212eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin return "Code_attribute{" + 213eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin "max_stack=" + max_stack + 214eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin ", max_locals=" + max_locals + 215eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin ", code_length=" + code_length + 216eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin ", code=" + Arrays.toString(code) + 217eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin ", exception_table_length=" + exception_table_length + 218eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin ", attributes_count=" + attributes_count + 219eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin '}'; 220eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 221eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 222eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 223eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin static class SourceFile_attribute { 224eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int sourcefile_index; 225eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 226eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin SourceFile_attribute(DataInputStream in) throws IOException { 227eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin sourcefile_index = in.readUnsignedShort(); 228eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 229eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 230eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin @Override 231eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public String toString() { 232eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin return "SourceFile_attribute{" + 233eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin "sourcefile_index=" + sourcefile_index + 234eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin '}'; 235eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 236eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 237eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 238eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin public void readClass(String classPath) throws IOException { 239eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin InputStream iin; 240eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin if(classPath.startsWith("classpath:")) { 241eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin String className = classPath.substring("classpath:".length()); 242eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin String resourceName = classNameToResource(className); 243eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin iin = getClass().getClassLoader().getResourceAsStream(resourceName); 244eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 245eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin else { 246eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin iin = new FileInputStream(classPath); 247eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 248eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 249eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin DataInputStream in = new DataInputStream(iin); 250eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 251eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin // magic number 252eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin in.read(buffer, 0, MAGIC.length); 253eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin assertArrayEquals(MAGIC); 254eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 255eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin // version 256eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin in.read(buffer, 0, VERSION.length); 257eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin assertArrayEquals(VERSION); 258eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 259eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin // constant_pool_count 260eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int constant_pool_count = in.readUnsignedShort(); 261eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.println("Constant pool count: " + constant_pool_count); 262eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 263eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin // indexed from 1 (0 will be unused) to constant_pool_count-1 264eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin constant_pool = new Object[constant_pool_count]; 265eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 266eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin // constant pool 267eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin for (int i = 1; i < constant_pool_count; i++) { 268eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.print(i + ": "); 269eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int type = in.readUnsignedByte(); 270eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin switch(type) { 271eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin case CONSTANT_Utf8: 272eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin constant_pool[i] = new CONSTANT_Utf8_info(in); 273eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin break; 274eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin case CONSTANT_Class: 275eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin constant_pool[i] = new CONSTANT_Class_info(in); 276eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin break; 277eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin case CONSTANT_Methodref: 278eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin constant_pool[i] = new CONSTANT_Methodref_info(in); 279eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin break; 280eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin case CONSTANT_NameAndType: 281eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin constant_pool[i] = new CONSTANT_NameAndType_info(in); 282eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin break; 283eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin default: 284eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin fail("Unknown type: " + type); 285eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 286eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.println(constant_pool[i]); 287eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 288eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 289eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin // access flags 290eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int access_flags = in.readUnsignedShort(); 291eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.println("Access flags: " + access_flags); // see http://stackoverflow.com/questions/8949933/what-is-the-purpose-of-the-acc-super-access-flag-on-java-class-files 292eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 293eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin // this class name 294eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int this_class = in.readUnsignedShort(); 295eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.println("This class index: " + this_class); 296eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 297eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin // super class name 298eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int super_class = in.readUnsignedShort(); 299eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.println("This superclass index: " + super_class); 300eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 301eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin // interfaces implemented count (we have none) 302eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int interfaces_count = in.readUnsignedShort(); 303eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.println("Interfaces count: " + interfaces_count); 304eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin for (int i = 0; i < interfaces_count; i++) { 305eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int index = in.readUnsignedShort(); 306eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.println("Interface " + i + " index: " + index); 307eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 308eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 309eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin // fields count (we have none) 310eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int fields_count = in.readUnsignedShort(); 311eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.println("Fields count: " + fields_count); 312eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin assertEquals("Reading fields isn't yet supported", 0, fields_count); 313eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 314eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin //methods count (we have one) 315eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int methods_count = in.readUnsignedShort(); 316eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.println("Methods count: " + methods_count); 317eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 318eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin for (int i = 0; i < methods_count; i++) { 319eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin method_info methodInfo = new method_info(in); 320eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.println("for " + methodInfo); 321eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 322eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 323eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin // reading final class attributes 324eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin int attributes_count = in.readUnsignedShort(); 325eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin System.out.println("Class attributes count: " + attributes_count); 326eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin for (int i = 0; i < attributes_count ; i++) { 327eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin attribute_info attributeInfo = new attribute_info(in); 328eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 329eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 330eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin in.close(); 331eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 332eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin 333eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin private void assertArrayEquals(byte[] expected) { 334eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin for (int i = 0; i < expected.length; i++) { 335eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin if(expected[i] != buffer[i]) { 336eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin fail("Expected was " + Arrays.toString(expected) + " but actual is " + Arrays.toString(buffer)); 337eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 338eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 339eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin } 340eebfcaffb2d52b214abfdb1c0102395c88c9db54Paul Duffin} 341