1fe7450192ce5268d73f19b404ca8d454023b3569cushon/* 2fe7450192ce5268d73f19b404ca8d454023b3569cushon * Copyright 2016 Google Inc. All Rights Reserved. 3fe7450192ce5268d73f19b404ca8d454023b3569cushon * 4fe7450192ce5268d73f19b404ca8d454023b3569cushon * Licensed under the Apache License, Version 2.0 (the "License"); 5fe7450192ce5268d73f19b404ca8d454023b3569cushon * you may not use this file except in compliance with the License. 6fe7450192ce5268d73f19b404ca8d454023b3569cushon * You may obtain a copy of the License at 7fe7450192ce5268d73f19b404ca8d454023b3569cushon * 8fe7450192ce5268d73f19b404ca8d454023b3569cushon * http://www.apache.org/licenses/LICENSE-2.0 9fe7450192ce5268d73f19b404ca8d454023b3569cushon * 10fe7450192ce5268d73f19b404ca8d454023b3569cushon * Unless required by applicable law or agreed to in writing, software 11fe7450192ce5268d73f19b404ca8d454023b3569cushon * distributed under the License is distributed on an "AS IS" BASIS, 12fe7450192ce5268d73f19b404ca8d454023b3569cushon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fe7450192ce5268d73f19b404ca8d454023b3569cushon * See the License for the specific language governing permissions and 14fe7450192ce5268d73f19b404ca8d454023b3569cushon * limitations under the License. 15fe7450192ce5268d73f19b404ca8d454023b3569cushon */ 16fe7450192ce5268d73f19b404ca8d454023b3569cushon 17fe7450192ce5268d73f19b404ca8d454023b3569cushonpackage com.google.turbine.bytecode; 18fe7450192ce5268d73f19b404ca8d454023b3569cushon 19783f80f37ad70eba7fd4b5e11a34854724227bf6cushonimport com.google.common.collect.ImmutableList; 20fe7450192ce5268d73f19b404ca8d454023b3569cushonimport com.google.common.collect.ImmutableMap; 21d01fe55c0e5007580f441eb336a14473e00b8f54cushonimport com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue; 2286eb6f1c5b02fc461b47602de67551361f9d695fcushonimport com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstClassValue; 23d01fe55c0e5007580f441eb336a14473e00b8f54cushonimport com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.EnumConstValue; 24fe7450192ce5268d73f19b404ca8d454023b3569cushonimport com.google.turbine.model.Const; 25fe7450192ce5268d73f19b404ca8d454023b3569cushonimport com.google.turbine.model.TurbineFlag; 26fe7450192ce5268d73f19b404ca8d454023b3569cushonimport java.util.ArrayList; 27fe7450192ce5268d73f19b404ca8d454023b3569cushonimport java.util.Collections; 28fe7450192ce5268d73f19b404ca8d454023b3569cushonimport java.util.List; 2928fc0ccb690cad787da840572c73fd3e3311047dcushonimport javax.annotation.CheckReturnValue; 3028fc0ccb690cad787da840572c73fd3e3311047dcushonimport javax.annotation.Nullable; 31fe7450192ce5268d73f19b404ca8d454023b3569cushon 32fe7450192ce5268d73f19b404ca8d454023b3569cushon/** A JVMS §4 class file reader. */ 33fe7450192ce5268d73f19b404ca8d454023b3569cushonpublic class ClassReader { 34fe7450192ce5268d73f19b404ca8d454023b3569cushon 35fe7450192ce5268d73f19b404ca8d454023b3569cushon /** Reads the given bytes into an {@link ClassFile}. */ 3628fc0ccb690cad787da840572c73fd3e3311047dcushon @Deprecated 37fe7450192ce5268d73f19b404ca8d454023b3569cushon public static ClassFile read(byte[] bytes) { 3828fc0ccb690cad787da840572c73fd3e3311047dcushon return read(null, bytes); 39fe7450192ce5268d73f19b404ca8d454023b3569cushon } 40fe7450192ce5268d73f19b404ca8d454023b3569cushon 4128fc0ccb690cad787da840572c73fd3e3311047dcushon /** Reads the given bytes into an {@link ClassFile}. */ 4228fc0ccb690cad787da840572c73fd3e3311047dcushon public static ClassFile read(@Nullable String path, byte[] bytes) { 4328fc0ccb690cad787da840572c73fd3e3311047dcushon return new ClassReader(path, bytes).read(); 4428fc0ccb690cad787da840572c73fd3e3311047dcushon } 4528fc0ccb690cad787da840572c73fd3e3311047dcushon 4628fc0ccb690cad787da840572c73fd3e3311047dcushon @Nullable private final String path; 47fe7450192ce5268d73f19b404ca8d454023b3569cushon private final ByteReader reader; 48fe7450192ce5268d73f19b404ca8d454023b3569cushon 4928fc0ccb690cad787da840572c73fd3e3311047dcushon private ClassReader(@Nullable String path, byte[] bytes) { 5028fc0ccb690cad787da840572c73fd3e3311047dcushon this.path = path; 51fe7450192ce5268d73f19b404ca8d454023b3569cushon this.reader = new ByteReader(bytes, 0); 52fe7450192ce5268d73f19b404ca8d454023b3569cushon } 53fe7450192ce5268d73f19b404ca8d454023b3569cushon 5428fc0ccb690cad787da840572c73fd3e3311047dcushon @CheckReturnValue 5528fc0ccb690cad787da840572c73fd3e3311047dcushon Error error(String format, Object... args) { 5628fc0ccb690cad787da840572c73fd3e3311047dcushon StringBuilder sb = new StringBuilder(); 5728fc0ccb690cad787da840572c73fd3e3311047dcushon if (path != null) { 5828fc0ccb690cad787da840572c73fd3e3311047dcushon sb.append(path).append(": "); 5928fc0ccb690cad787da840572c73fd3e3311047dcushon } 6028fc0ccb690cad787da840572c73fd3e3311047dcushon sb.append(String.format(format, args)); 6128fc0ccb690cad787da840572c73fd3e3311047dcushon return new AssertionError(sb.toString()); 6228fc0ccb690cad787da840572c73fd3e3311047dcushon } 6328fc0ccb690cad787da840572c73fd3e3311047dcushon 64fe7450192ce5268d73f19b404ca8d454023b3569cushon private ClassFile read() { 65fe7450192ce5268d73f19b404ca8d454023b3569cushon int magic = reader.u4(); 66fe7450192ce5268d73f19b404ca8d454023b3569cushon if (magic != 0xcafebabe) { 6728fc0ccb690cad787da840572c73fd3e3311047dcushon throw error("bad magic: 0x%x", path, magic); 68fe7450192ce5268d73f19b404ca8d454023b3569cushon } 697700e365dd9cd14b9a03bda4cf10bc9f7dc1d8d4cushon int minorVersion = reader.u2(); 707700e365dd9cd14b9a03bda4cf10bc9f7dc1d8d4cushon int majorVersion = reader.u2(); 7128fc0ccb690cad787da840572c73fd3e3311047dcushon if (majorVersion < 45 || majorVersion > 53) { 7228fc0ccb690cad787da840572c73fd3e3311047dcushon throw error("bad version: %d.%d", majorVersion, minorVersion); 73fe7450192ce5268d73f19b404ca8d454023b3569cushon } 74fe7450192ce5268d73f19b404ca8d454023b3569cushon ConstantPoolReader constantPool = ConstantPoolReader.readConstantPool(reader); 757700e365dd9cd14b9a03bda4cf10bc9f7dc1d8d4cushon int accessFlags = reader.u2(); 76fe7450192ce5268d73f19b404ca8d454023b3569cushon String thisClass = constantPool.classInfo(reader.u2()); 777700e365dd9cd14b9a03bda4cf10bc9f7dc1d8d4cushon int superClassIndex = reader.u2(); 78fe7450192ce5268d73f19b404ca8d454023b3569cushon String superClass; 79fe7450192ce5268d73f19b404ca8d454023b3569cushon if (superClassIndex != 0) { 80fe7450192ce5268d73f19b404ca8d454023b3569cushon superClass = constantPool.classInfo(superClassIndex); 81fe7450192ce5268d73f19b404ca8d454023b3569cushon } else { 82fe7450192ce5268d73f19b404ca8d454023b3569cushon superClass = null; 83fe7450192ce5268d73f19b404ca8d454023b3569cushon } 847700e365dd9cd14b9a03bda4cf10bc9f7dc1d8d4cushon int interfacesCount = reader.u2(); 85fe7450192ce5268d73f19b404ca8d454023b3569cushon List<String> interfaces = new ArrayList<>(); 86fe7450192ce5268d73f19b404ca8d454023b3569cushon for (int i = 0; i < interfacesCount; i++) { 87fe7450192ce5268d73f19b404ca8d454023b3569cushon interfaces.add(constantPool.classInfo(reader.u2())); 88fe7450192ce5268d73f19b404ca8d454023b3569cushon } 89fe7450192ce5268d73f19b404ca8d454023b3569cushon 90d01fe55c0e5007580f441eb336a14473e00b8f54cushon List<ClassFile.FieldInfo> fieldinfos = readFields(constantPool); 91fe7450192ce5268d73f19b404ca8d454023b3569cushon 92d01fe55c0e5007580f441eb336a14473e00b8f54cushon List<ClassFile.MethodInfo> methodinfos = readMethods(constantPool); 93fe7450192ce5268d73f19b404ca8d454023b3569cushon 94fe7450192ce5268d73f19b404ca8d454023b3569cushon String signature = null; 95d01fe55c0e5007580f441eb336a14473e00b8f54cushon List<ClassFile.InnerClass> innerclasses = Collections.emptyList(); 96d01fe55c0e5007580f441eb336a14473e00b8f54cushon List<ClassFile.AnnotationInfo> annotations = Collections.emptyList(); 97fe7450192ce5268d73f19b404ca8d454023b3569cushon int attributesCount = reader.u2(); 98fe7450192ce5268d73f19b404ca8d454023b3569cushon for (int j = 0; j < attributesCount; j++) { 99fe7450192ce5268d73f19b404ca8d454023b3569cushon int attributeNameIndex = reader.u2(); 100fe7450192ce5268d73f19b404ca8d454023b3569cushon String name = constantPool.utf8(attributeNameIndex); 101fe7450192ce5268d73f19b404ca8d454023b3569cushon switch (name) { 102fe7450192ce5268d73f19b404ca8d454023b3569cushon case "RuntimeVisibleAnnotations": 103fe7450192ce5268d73f19b404ca8d454023b3569cushon annotations = readAnnotations(constantPool, accessFlags); 104fe7450192ce5268d73f19b404ca8d454023b3569cushon break; 105fe7450192ce5268d73f19b404ca8d454023b3569cushon case "Signature": 106fe7450192ce5268d73f19b404ca8d454023b3569cushon signature = readSignature(constantPool); 107fe7450192ce5268d73f19b404ca8d454023b3569cushon break; 108fe7450192ce5268d73f19b404ca8d454023b3569cushon case "InnerClasses": 109fe7450192ce5268d73f19b404ca8d454023b3569cushon innerclasses = readInnerClasses(constantPool, thisClass); 110fe7450192ce5268d73f19b404ca8d454023b3569cushon break; 111fe7450192ce5268d73f19b404ca8d454023b3569cushon default: 112fe7450192ce5268d73f19b404ca8d454023b3569cushon reader.skip(reader.u4()); 113fe7450192ce5268d73f19b404ca8d454023b3569cushon break; 114fe7450192ce5268d73f19b404ca8d454023b3569cushon } 115fe7450192ce5268d73f19b404ca8d454023b3569cushon } 116fe7450192ce5268d73f19b404ca8d454023b3569cushon 117fe7450192ce5268d73f19b404ca8d454023b3569cushon return new ClassFile( 118fe7450192ce5268d73f19b404ca8d454023b3569cushon accessFlags, 119fe7450192ce5268d73f19b404ca8d454023b3569cushon thisClass, 120fe7450192ce5268d73f19b404ca8d454023b3569cushon signature, 121fe7450192ce5268d73f19b404ca8d454023b3569cushon superClass, 122fe7450192ce5268d73f19b404ca8d454023b3569cushon interfaces, 123fe7450192ce5268d73f19b404ca8d454023b3569cushon methodinfos, 124fe7450192ce5268d73f19b404ca8d454023b3569cushon fieldinfos, 125fe7450192ce5268d73f19b404ca8d454023b3569cushon annotations, 1263e5b0c401c8d93182e9f0ce6f0de81f7574f5acacushon innerclasses, 1273e5b0c401c8d93182e9f0ce6f0de81f7574f5acacushon ImmutableList.of()); 128fe7450192ce5268d73f19b404ca8d454023b3569cushon } 129fe7450192ce5268d73f19b404ca8d454023b3569cushon 130fe7450192ce5268d73f19b404ca8d454023b3569cushon /** Reads a JVMS 4.7.9 Signature attribute. */ 131fe7450192ce5268d73f19b404ca8d454023b3569cushon private String readSignature(ConstantPoolReader constantPool) { 132fe7450192ce5268d73f19b404ca8d454023b3569cushon String signature; 133fe7450192ce5268d73f19b404ca8d454023b3569cushon reader.u4(); // length 134fe7450192ce5268d73f19b404ca8d454023b3569cushon signature = constantPool.utf8(reader.u2()); 135fe7450192ce5268d73f19b404ca8d454023b3569cushon return signature; 136fe7450192ce5268d73f19b404ca8d454023b3569cushon } 137fe7450192ce5268d73f19b404ca8d454023b3569cushon 138fe7450192ce5268d73f19b404ca8d454023b3569cushon /** Reads JVMS 4.7.6 InnerClasses attributes. */ 139d01fe55c0e5007580f441eb336a14473e00b8f54cushon private List<ClassFile.InnerClass> readInnerClasses( 140d01fe55c0e5007580f441eb336a14473e00b8f54cushon ConstantPoolReader constantPool, String thisClass) { 141fe7450192ce5268d73f19b404ca8d454023b3569cushon reader.u4(); // length 142fe7450192ce5268d73f19b404ca8d454023b3569cushon int numberOfClasses = reader.u2(); 143d01fe55c0e5007580f441eb336a14473e00b8f54cushon List<ClassFile.InnerClass> innerclasses = new ArrayList<>(); 144fe7450192ce5268d73f19b404ca8d454023b3569cushon for (int i = 0; i < numberOfClasses; i++) { 145fe7450192ce5268d73f19b404ca8d454023b3569cushon int innerClassInfoIndex = reader.u2(); 146fe7450192ce5268d73f19b404ca8d454023b3569cushon String innerClass = constantPool.classInfo(innerClassInfoIndex); 147fe7450192ce5268d73f19b404ca8d454023b3569cushon int outerClassInfoIndex = reader.u2(); 148fe7450192ce5268d73f19b404ca8d454023b3569cushon String outerClass = 149fe7450192ce5268d73f19b404ca8d454023b3569cushon outerClassInfoIndex != 0 ? constantPool.classInfo(outerClassInfoIndex) : null; 150fe7450192ce5268d73f19b404ca8d454023b3569cushon int innerNameIndex = reader.u2(); 151fe7450192ce5268d73f19b404ca8d454023b3569cushon String innerName = innerNameIndex != 0 ? constantPool.utf8(innerNameIndex) : null; 1527700e365dd9cd14b9a03bda4cf10bc9f7dc1d8d4cushon int innerClassAccessFlags = reader.u2(); 1534a9a664dd17b17d4ca4641f6267a59f644f20a07cushon if (innerName != null && (thisClass.equals(innerClass) || thisClass.equals(outerClass))) { 154d01fe55c0e5007580f441eb336a14473e00b8f54cushon innerclasses.add( 155d01fe55c0e5007580f441eb336a14473e00b8f54cushon new ClassFile.InnerClass(innerClass, outerClass, innerName, innerClassAccessFlags)); 156fe7450192ce5268d73f19b404ca8d454023b3569cushon } 157fe7450192ce5268d73f19b404ca8d454023b3569cushon } 158fe7450192ce5268d73f19b404ca8d454023b3569cushon return innerclasses; 159fe7450192ce5268d73f19b404ca8d454023b3569cushon } 160fe7450192ce5268d73f19b404ca8d454023b3569cushon 161fe7450192ce5268d73f19b404ca8d454023b3569cushon /** 162fe7450192ce5268d73f19b404ca8d454023b3569cushon * Processes a JVMS 4.7.16 RuntimeVisibleAnnotations attribute. 163fe7450192ce5268d73f19b404ca8d454023b3569cushon * 164ecb791c15008191f75be7a7e747bb387530d16d2cushon * <p>The only annotations that affect header compilation are {@link @Retention} and 165ecb791c15008191f75be7a7e747bb387530d16d2cushon * {@link @Target} on annotation declarations. 166fe7450192ce5268d73f19b404ca8d454023b3569cushon */ 167d01fe55c0e5007580f441eb336a14473e00b8f54cushon private List<ClassFile.AnnotationInfo> readAnnotations( 1687700e365dd9cd14b9a03bda4cf10bc9f7dc1d8d4cushon ConstantPoolReader constantPool, int accessFlags) { 169d01fe55c0e5007580f441eb336a14473e00b8f54cushon List<ClassFile.AnnotationInfo> annotations = new ArrayList<>(); 170fe7450192ce5268d73f19b404ca8d454023b3569cushon if ((accessFlags & TurbineFlag.ACC_ANNOTATION) == 0) { 171fe7450192ce5268d73f19b404ca8d454023b3569cushon reader.skip(reader.u4()); 172d1509927c68b994ecb9eb95a8ae8478da9f04ed4cushon return ImmutableList.of(); 173fe7450192ce5268d73f19b404ca8d454023b3569cushon } 174fe7450192ce5268d73f19b404ca8d454023b3569cushon reader.u4(); // length 175fe7450192ce5268d73f19b404ca8d454023b3569cushon int numAnnotations = reader.u2(); 176fe7450192ce5268d73f19b404ca8d454023b3569cushon for (int n = 0; n < numAnnotations; n++) { 177d01fe55c0e5007580f441eb336a14473e00b8f54cushon ClassFile.AnnotationInfo tmp = readAnnotation(constantPool); 178fe7450192ce5268d73f19b404ca8d454023b3569cushon if (tmp != null) { 179fe7450192ce5268d73f19b404ca8d454023b3569cushon annotations.add(tmp); 180fe7450192ce5268d73f19b404ca8d454023b3569cushon } 181fe7450192ce5268d73f19b404ca8d454023b3569cushon } 182fe7450192ce5268d73f19b404ca8d454023b3569cushon return annotations; 183fe7450192ce5268d73f19b404ca8d454023b3569cushon } 184fe7450192ce5268d73f19b404ca8d454023b3569cushon 185d01fe55c0e5007580f441eb336a14473e00b8f54cushon /** 186ecb791c15008191f75be7a7e747bb387530d16d2cushon * Extracts an {@link @Retention} or {@link ElementType} {@link ClassFile.AnnotationInfo}, or else 187ecb791c15008191f75be7a7e747bb387530d16d2cushon * skips over the annotation. 188d01fe55c0e5007580f441eb336a14473e00b8f54cushon */ 189d01fe55c0e5007580f441eb336a14473e00b8f54cushon private ClassFile.AnnotationInfo readAnnotation(ConstantPoolReader constantPool) { 190fe7450192ce5268d73f19b404ca8d454023b3569cushon int typeIndex = reader.u2(); 191fe7450192ce5268d73f19b404ca8d454023b3569cushon String annotationType = constantPool.utf8(typeIndex); 192ecb791c15008191f75be7a7e747bb387530d16d2cushon boolean read; 193ecb791c15008191f75be7a7e747bb387530d16d2cushon switch (annotationType) { 194ecb791c15008191f75be7a7e747bb387530d16d2cushon case "Ljava/lang/annotation/Retention;": 195ecb791c15008191f75be7a7e747bb387530d16d2cushon case "Ljava/lang/annotation/Target;": 19686eb6f1c5b02fc461b47602de67551361f9d695fcushon case "Ljava/lang/annotation/Repeatable;": 197ecb791c15008191f75be7a7e747bb387530d16d2cushon read = true; 198ecb791c15008191f75be7a7e747bb387530d16d2cushon break; 199ecb791c15008191f75be7a7e747bb387530d16d2cushon default: 200ecb791c15008191f75be7a7e747bb387530d16d2cushon read = false; 201ecb791c15008191f75be7a7e747bb387530d16d2cushon break; 202ecb791c15008191f75be7a7e747bb387530d16d2cushon } 203fe7450192ce5268d73f19b404ca8d454023b3569cushon int numElementValuePairs = reader.u2(); 204d01fe55c0e5007580f441eb336a14473e00b8f54cushon ClassFile.AnnotationInfo result = null; 205fe7450192ce5268d73f19b404ca8d454023b3569cushon for (int e = 0; e < numElementValuePairs; e++) { 206fe7450192ce5268d73f19b404ca8d454023b3569cushon int elementNameIndex = reader.u2(); 207fe7450192ce5268d73f19b404ca8d454023b3569cushon String key = constantPool.utf8(elementNameIndex); 208ecb791c15008191f75be7a7e747bb387530d16d2cushon boolean value = read && key.equals("value"); 209fe7450192ce5268d73f19b404ca8d454023b3569cushon ElementValue tmp = readElementValue(constantPool, value); 210fe7450192ce5268d73f19b404ca8d454023b3569cushon if (tmp != null) { 211d01fe55c0e5007580f441eb336a14473e00b8f54cushon result = new ClassFile.AnnotationInfo(annotationType, true, ImmutableMap.of(key, tmp)); 212fe7450192ce5268d73f19b404ca8d454023b3569cushon } 213fe7450192ce5268d73f19b404ca8d454023b3569cushon } 214fe7450192ce5268d73f19b404ca8d454023b3569cushon return result; 215fe7450192ce5268d73f19b404ca8d454023b3569cushon } 216fe7450192ce5268d73f19b404ca8d454023b3569cushon 217fe7450192ce5268d73f19b404ca8d454023b3569cushon /** 21886eb6f1c5b02fc461b47602de67551361f9d695fcushon * Extracts the value of an annotation declaration meta-annotation, or else skips over the element 21986eb6f1c5b02fc461b47602de67551361f9d695fcushon * value pair. 220fe7450192ce5268d73f19b404ca8d454023b3569cushon */ 221fe7450192ce5268d73f19b404ca8d454023b3569cushon private ElementValue readElementValue(ConstantPoolReader constantPool, boolean value) { 222fe7450192ce5268d73f19b404ca8d454023b3569cushon int tag = reader.u1(); 223fe7450192ce5268d73f19b404ca8d454023b3569cushon switch (tag) { 224fe7450192ce5268d73f19b404ca8d454023b3569cushon case 'B': 225fe7450192ce5268d73f19b404ca8d454023b3569cushon case 'C': 226fe7450192ce5268d73f19b404ca8d454023b3569cushon case 'D': 227fe7450192ce5268d73f19b404ca8d454023b3569cushon case 'F': 228fe7450192ce5268d73f19b404ca8d454023b3569cushon case 'I': 229fe7450192ce5268d73f19b404ca8d454023b3569cushon case 'J': 230fe7450192ce5268d73f19b404ca8d454023b3569cushon case 'S': 231fe7450192ce5268d73f19b404ca8d454023b3569cushon case 'Z': 232fe7450192ce5268d73f19b404ca8d454023b3569cushon case 's': 233fe7450192ce5268d73f19b404ca8d454023b3569cushon reader.u2(); // constValueIndex 234fe7450192ce5268d73f19b404ca8d454023b3569cushon break; 235fe7450192ce5268d73f19b404ca8d454023b3569cushon case 'e': 236fe7450192ce5268d73f19b404ca8d454023b3569cushon { 237fe7450192ce5268d73f19b404ca8d454023b3569cushon int typeNameIndex = reader.u2(); 238fe7450192ce5268d73f19b404ca8d454023b3569cushon int constNameIndex = reader.u2(); 239fe7450192ce5268d73f19b404ca8d454023b3569cushon if (value) { 240fe7450192ce5268d73f19b404ca8d454023b3569cushon String typeName = constantPool.utf8(typeNameIndex); 241ecb791c15008191f75be7a7e747bb387530d16d2cushon switch (typeName) { 242ecb791c15008191f75be7a7e747bb387530d16d2cushon case "Ljava/lang/annotation/RetentionPolicy;": 243ecb791c15008191f75be7a7e747bb387530d16d2cushon case "Ljava/lang/annotation/ElementType;": 244ecb791c15008191f75be7a7e747bb387530d16d2cushon String constName = constantPool.utf8(constNameIndex); 245ecb791c15008191f75be7a7e747bb387530d16d2cushon return new EnumConstValue(typeName, constName); 246ecb791c15008191f75be7a7e747bb387530d16d2cushon default: 247ecb791c15008191f75be7a7e747bb387530d16d2cushon break; 248fe7450192ce5268d73f19b404ca8d454023b3569cushon } 249fe7450192ce5268d73f19b404ca8d454023b3569cushon } 250fe7450192ce5268d73f19b404ca8d454023b3569cushon break; 251fe7450192ce5268d73f19b404ca8d454023b3569cushon } 252fe7450192ce5268d73f19b404ca8d454023b3569cushon case 'c': 25386eb6f1c5b02fc461b47602de67551361f9d695fcushon int classInfoIndex = reader.u2(); 25486eb6f1c5b02fc461b47602de67551361f9d695fcushon String className = constantPool.utf8(classInfoIndex); 25586eb6f1c5b02fc461b47602de67551361f9d695fcushon return new ConstClassValue(className); 256fe7450192ce5268d73f19b404ca8d454023b3569cushon case '@': 257fe7450192ce5268d73f19b404ca8d454023b3569cushon readAnnotation(constantPool); 258fe7450192ce5268d73f19b404ca8d454023b3569cushon break; 259fe7450192ce5268d73f19b404ca8d454023b3569cushon case '[': 260fe7450192ce5268d73f19b404ca8d454023b3569cushon { 261fe7450192ce5268d73f19b404ca8d454023b3569cushon int numValues = reader.u2(); 262ecb791c15008191f75be7a7e747bb387530d16d2cushon if (value) { 263ecb791c15008191f75be7a7e747bb387530d16d2cushon ImmutableList.Builder<ElementValue> elements = ImmutableList.builder(); 264ecb791c15008191f75be7a7e747bb387530d16d2cushon for (int i = 0; i < numValues; i++) { 265ecb791c15008191f75be7a7e747bb387530d16d2cushon elements.add(readElementValue(constantPool, true)); 266ecb791c15008191f75be7a7e747bb387530d16d2cushon } 267ecb791c15008191f75be7a7e747bb387530d16d2cushon return new ElementValue.ArrayValue(elements.build()); 268ecb791c15008191f75be7a7e747bb387530d16d2cushon } else { 269ecb791c15008191f75be7a7e747bb387530d16d2cushon for (int i = 0; i < numValues; i++) { 270ecb791c15008191f75be7a7e747bb387530d16d2cushon readElementValue(constantPool, false); 271ecb791c15008191f75be7a7e747bb387530d16d2cushon } 272fe7450192ce5268d73f19b404ca8d454023b3569cushon } 273fe7450192ce5268d73f19b404ca8d454023b3569cushon break; 274fe7450192ce5268d73f19b404ca8d454023b3569cushon } 275fe7450192ce5268d73f19b404ca8d454023b3569cushon default: 27628fc0ccb690cad787da840572c73fd3e3311047dcushon throw error("bad tag value %c", tag); 277fe7450192ce5268d73f19b404ca8d454023b3569cushon } 278fe7450192ce5268d73f19b404ca8d454023b3569cushon return null; 279fe7450192ce5268d73f19b404ca8d454023b3569cushon } 280fe7450192ce5268d73f19b404ca8d454023b3569cushon 281fe7450192ce5268d73f19b404ca8d454023b3569cushon /** Reads JVMS 4.6 method_infos. */ 282d01fe55c0e5007580f441eb336a14473e00b8f54cushon private List<ClassFile.MethodInfo> readMethods(ConstantPoolReader constantPool) { 283fe7450192ce5268d73f19b404ca8d454023b3569cushon int methodsCount = reader.u2(); 284d01fe55c0e5007580f441eb336a14473e00b8f54cushon List<ClassFile.MethodInfo> methods = new ArrayList<>(); 285fe7450192ce5268d73f19b404ca8d454023b3569cushon for (int i = 0; i < methodsCount; i++) { 286fe7450192ce5268d73f19b404ca8d454023b3569cushon int accessFlags = reader.u2(); 287fe7450192ce5268d73f19b404ca8d454023b3569cushon int nameIndex = reader.u2(); 288fe7450192ce5268d73f19b404ca8d454023b3569cushon String name = constantPool.utf8(nameIndex); 289fe7450192ce5268d73f19b404ca8d454023b3569cushon int descriptorIndex = reader.u2(); 290fe7450192ce5268d73f19b404ca8d454023b3569cushon String desc = constantPool.utf8(descriptorIndex); 291fe7450192ce5268d73f19b404ca8d454023b3569cushon int attributesCount = reader.u2(); 292fe7450192ce5268d73f19b404ca8d454023b3569cushon String signature = null; 293783f80f37ad70eba7fd4b5e11a34854724227bf6cushon ImmutableList<String> exceptions = ImmutableList.of(); 294fe7450192ce5268d73f19b404ca8d454023b3569cushon for (int j = 0; j < attributesCount; j++) { 295fe7450192ce5268d73f19b404ca8d454023b3569cushon String attributeName = constantPool.utf8(reader.u2()); 296fe7450192ce5268d73f19b404ca8d454023b3569cushon switch (attributeName) { 297fe7450192ce5268d73f19b404ca8d454023b3569cushon case "Exceptions": 298fe7450192ce5268d73f19b404ca8d454023b3569cushon exceptions = readExceptions(constantPool); 299fe7450192ce5268d73f19b404ca8d454023b3569cushon break; 300fe7450192ce5268d73f19b404ca8d454023b3569cushon case "Signature": 301fe7450192ce5268d73f19b404ca8d454023b3569cushon signature = readSignature(constantPool); 302fe7450192ce5268d73f19b404ca8d454023b3569cushon break; 303fe7450192ce5268d73f19b404ca8d454023b3569cushon default: 304fe7450192ce5268d73f19b404ca8d454023b3569cushon reader.skip(reader.u4()); 305fe7450192ce5268d73f19b404ca8d454023b3569cushon break; 306fe7450192ce5268d73f19b404ca8d454023b3569cushon } 307fe7450192ce5268d73f19b404ca8d454023b3569cushon } 308fe7450192ce5268d73f19b404ca8d454023b3569cushon methods.add( 309d01fe55c0e5007580f441eb336a14473e00b8f54cushon new ClassFile.MethodInfo( 310fe7450192ce5268d73f19b404ca8d454023b3569cushon accessFlags, 311fe7450192ce5268d73f19b404ca8d454023b3569cushon name, 312fe7450192ce5268d73f19b404ca8d454023b3569cushon desc, 313fe7450192ce5268d73f19b404ca8d454023b3569cushon signature, 314fe7450192ce5268d73f19b404ca8d454023b3569cushon exceptions, 315fe7450192ce5268d73f19b404ca8d454023b3569cushon null, 3163088f83b806b82d866d119e344da274105f42821cushon ImmutableList.of(), 3173e5b0c401c8d93182e9f0ce6f0de81f7574f5acacushon ImmutableList.of(), 3183d2df35d983a31bc7a68e1d76b7c71956f477871cushon ImmutableList.of(), 3193088f83b806b82d866d119e344da274105f42821cushon ImmutableList.of())); 320fe7450192ce5268d73f19b404ca8d454023b3569cushon } 321fe7450192ce5268d73f19b404ca8d454023b3569cushon return methods; 322fe7450192ce5268d73f19b404ca8d454023b3569cushon } 323fe7450192ce5268d73f19b404ca8d454023b3569cushon 324fe7450192ce5268d73f19b404ca8d454023b3569cushon /** Reads an Exceptions attribute. */ 325783f80f37ad70eba7fd4b5e11a34854724227bf6cushon private ImmutableList<String> readExceptions(ConstantPoolReader constantPool) { 326783f80f37ad70eba7fd4b5e11a34854724227bf6cushon ImmutableList.Builder<String> exceptions = ImmutableList.builder(); 327fe7450192ce5268d73f19b404ca8d454023b3569cushon reader.u4(); // length 328fe7450192ce5268d73f19b404ca8d454023b3569cushon int numberOfExceptions = reader.u2(); 329fe7450192ce5268d73f19b404ca8d454023b3569cushon for (int exceptionIndex = 0; exceptionIndex < numberOfExceptions; exceptionIndex++) { 330fe7450192ce5268d73f19b404ca8d454023b3569cushon exceptions.add(constantPool.classInfo(reader.u2())); 331fe7450192ce5268d73f19b404ca8d454023b3569cushon } 332783f80f37ad70eba7fd4b5e11a34854724227bf6cushon return exceptions.build(); 333fe7450192ce5268d73f19b404ca8d454023b3569cushon } 334fe7450192ce5268d73f19b404ca8d454023b3569cushon 335fe7450192ce5268d73f19b404ca8d454023b3569cushon /** Reads JVMS 4.5 field_infos. */ 336d01fe55c0e5007580f441eb336a14473e00b8f54cushon private List<ClassFile.FieldInfo> readFields(ConstantPoolReader constantPool) { 337fe7450192ce5268d73f19b404ca8d454023b3569cushon int fieldsCount = reader.u2(); 338d01fe55c0e5007580f441eb336a14473e00b8f54cushon List<ClassFile.FieldInfo> fields = new ArrayList<>(); 339fe7450192ce5268d73f19b404ca8d454023b3569cushon for (int i = 0; i < fieldsCount; i++) { 340fe7450192ce5268d73f19b404ca8d454023b3569cushon int accessFlags = reader.u2(); 341fe7450192ce5268d73f19b404ca8d454023b3569cushon int nameIndex = reader.u2(); 342fe7450192ce5268d73f19b404ca8d454023b3569cushon String name = constantPool.utf8(nameIndex); 343fe7450192ce5268d73f19b404ca8d454023b3569cushon int descriptorIndex = reader.u2(); 344fe7450192ce5268d73f19b404ca8d454023b3569cushon String desc = constantPool.utf8(descriptorIndex); 345fe7450192ce5268d73f19b404ca8d454023b3569cushon int attributesCount = reader.u2(); 346fe7450192ce5268d73f19b404ca8d454023b3569cushon Const.Value value = null; 347fe7450192ce5268d73f19b404ca8d454023b3569cushon for (int j = 0; j < attributesCount; j++) { 348fe7450192ce5268d73f19b404ca8d454023b3569cushon String attributeName = constantPool.utf8(reader.u2()); 349fe7450192ce5268d73f19b404ca8d454023b3569cushon switch (attributeName) { 350fe7450192ce5268d73f19b404ca8d454023b3569cushon case "ConstantValue": 351fe7450192ce5268d73f19b404ca8d454023b3569cushon reader.u4(); // length 352fe7450192ce5268d73f19b404ca8d454023b3569cushon value = constantPool.constant(reader.u2()); 353fe7450192ce5268d73f19b404ca8d454023b3569cushon break; 354fe7450192ce5268d73f19b404ca8d454023b3569cushon default: 355fe7450192ce5268d73f19b404ca8d454023b3569cushon reader.skip(reader.u4()); 356fe7450192ce5268d73f19b404ca8d454023b3569cushon break; 357fe7450192ce5268d73f19b404ca8d454023b3569cushon } 358fe7450192ce5268d73f19b404ca8d454023b3569cushon } 359fe7450192ce5268d73f19b404ca8d454023b3569cushon fields.add( 360d01fe55c0e5007580f441eb336a14473e00b8f54cushon new ClassFile.FieldInfo( 361fe7450192ce5268d73f19b404ca8d454023b3569cushon accessFlags, 362fe7450192ce5268d73f19b404ca8d454023b3569cushon name, 363fe7450192ce5268d73f19b404ca8d454023b3569cushon desc, 364fe7450192ce5268d73f19b404ca8d454023b3569cushon /*signature*/ null, 365fe7450192ce5268d73f19b404ca8d454023b3569cushon value, 3663e5b0c401c8d93182e9f0ce6f0de81f7574f5acacushon ImmutableList.of(), 3673e5b0c401c8d93182e9f0ce6f0de81f7574f5acacushon ImmutableList.of())); 368fe7450192ce5268d73f19b404ca8d454023b3569cushon } 369fe7450192ce5268d73f19b404ca8d454023b3569cushon return fields; 370fe7450192ce5268d73f19b404ca8d454023b3569cushon } 371fe7450192ce5268d73f19b404ca8d454023b3569cushon} 372