1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | package Torello.Java.Additional; import java.util.Arrays; import java.nio.charset.StandardCharsets; // This class, sort of, isolates the contents of the Constructor into a single method. This // class is not an End-User API method. It isn't that nice to look at, and there really isn't // a way to make it look better. // // Instead, since the contents of this class lone method contain all details for reading // constants out of the Constant-Pool class ReadConstant { // Reads one contant from the Constant-Pool (via/using the Class-File as-a Byte-Array) // This method is Package-Private, and is only called - ONCE, IN ONE PLACE - inside the // constructor for ConstantPool static Object read( final byte[] bArr, final byte tagAsByte, final int index ) { switch (tagAsByte) { // public static final byte TAG_UTF_8 = 1; case 1: // CONSTANT_UTF_8 // First 2 bytes at the given index store the length of the UTF-8 string. int utf8Length = ((bArr[index] & 0xFF) << 8) | (bArr[index + 1] & 0xFF); // Extract the UTF-8 string from the byte array starting at index + 2 byte[] utf8Bytes = Arrays.copyOfRange (bArr, index + 2, index + 2 + utf8Length); // Convert the byte array into a String and return it return new String(utf8Bytes, StandardCharsets.UTF_8); // public static final byte TAG_INTEGER = 3; case 3: return Integer.valueOf( (bArr[index] & 0xFF) << 24 | (bArr[index + 1] & 0xFF) << 16 | (bArr[index + 2] & 0xFF) << 8 | (bArr[index + 3] & 0xFF) ); // public static final byte TAG_FLOAT = 4; case 4: return Float.intBitsToFloat( (bArr[index] & 0xFF) << 24 | (bArr[index + 1] & 0xFF) << 16 | (bArr[index + 2] & 0xFF) << 8 | (bArr[index + 3] & 0xFF) ); // public static final byte TAG_LONG = 5; case 5: return Long.valueOf( ((long) (bArr[index] & 0xFF) << 56) | ((long) (bArr[index + 1] & 0xFF) << 48) | ((long) (bArr[index + 2] & 0xFF) << 40) | ((long) (bArr[index + 3] & 0xFF) << 32) | ((long) (bArr[index + 4] & 0xFF) << 24) | ((long) (bArr[index + 5] & 0xFF) << 16) | ((long) (bArr[index + 6] & 0xFF) << 8) | ((long) (bArr[index + 7] & 0xFF)) ); // public static final byte TAG_DOUBLE = 6; case 6: long bits = ((long) (bArr[index] & 0xFF) << 56) | ((long) (bArr[index + 1] & 0xFF) << 48) | ((long) (bArr[index + 2] & 0xFF) << 40) | ((long) (bArr[index + 3] & 0xFF) << 32) | ((long) (bArr[index + 4] & 0xFF) << 24) | ((long) (bArr[index + 5] & 0xFF) << 16) | ((long) (bArr[index + 6] & 0xFF) << 8) | ((long) (bArr[index + 7] & 0xFF)); return Double.longBitsToDouble(bits); // public static final byte TAG_CLASS = 7; // public static final byte TAG_STRING = 8; // public static final byte TAG_METHOD_TYPE = 16; // public static final byte TAG_MODULE = 19; // public static final byte TAG_PACKAGE = 20; case 7: // CONSTANT_Class case 8: // CONSTANT_String case 16: // CONSTANT_MethodType case 19: // CONSTANT_Module case 20: // CONSTANT_Package // 2 bytes for the index to a CONSTANT_Utf8 string return Integer.valueOf((bArr[index] & 0xFF) << 8 | (bArr[index + 1] & 0xFF)); // public static final byte TAG_FIELD_REF = 9; // public static final byte TAG_METHOD_REF = 10; // public static final byte TAG_INTERFACE_METHOD_REF = 11; // public static final byte TAG_NAME_AND_TYPE = 12; // public static final byte TAG_DYNAMIC = 17; // public static final byte TAG_INVOKE_DYNAMIC = 18; case 9: // CONSTANT_Fieldref case 10: // CONSTANT_Methodref case 11: // CONSTANT_InterfaceMethodref case 12: // CONSTANT_NameAndType // Each reference stores 2 indices case 17: // CONSTANT_Dynamic // 2 bytes for the bootstrap method index + // 2 bytes for the name and type index case 18: // CONSTANT_InvokeDynamic // 2 bytes for the bootstrap method index + // 2 bytes for the name and type index final int index1 = ((bArr[index] & 0xFF) << 8) | (bArr[index + 1] & 0xFF); final int index2 = ((bArr[index + 2] & 0xFF) << 8) | (bArr[index + 3] & 0xFF); return new Ret2<Integer, Integer> (Integer.valueOf(index1), Integer.valueOf(index2)); // public static final byte TAG_METHOD_HANDLE = 15; case 15: // CONSTANT_MethodHandle // 1 byte for reference kind + 2 bytes for index // The reference kind is stored in the first byte // The index is a 2-byte value, which follows final byte kind = bArr[index]; final int i = ((bArr[index + 1] & 0xFF) << 8) | (bArr[index + 2] & 0xFF); return new Ret2<Byte, Integer>(Byte.valueOf(kind), Integer.valueOf(i)); // This cannot happen unless a corrupted Class-File was provided to the Constructor. // // The only other possibility is that Java-Oracle has created new constants since // the writing of this class. default: throw new ClassFileArrayException( "While parsing the Constant-Pool Table, an unknown constant pool tag " + "Byte-Value [" + tagAsByte + "]\n" + "This is likely caused by an invalid Java '.class' File" ); } } } |