public Void visitBootstrapMethods(BootstrapMethods_attribute attr, Void p) { println(Attribute.BootstrapMethods + ":"); for (int i = 0; i < attr.bootstrap_method_specifiers.length ; i++) { BootstrapMethods_attribute.BootstrapMethodSpecifier bsm = attr.bootstrap_method_specifiers[i]; indent(+1); print(i + ": #" + bsm.bootstrap_method_ref + " "); println(constantWriter.stringValue(bsm.bootstrap_method_ref)); indent(+1); println("Method arguments:"); indent(+1); for (int j = 0; j < bsm.bootstrap_arguments.length; j++) { print("#" + bsm.bootstrap_arguments[j] + " "); println(constantWriter.stringValue(bsm.bootstrap_arguments[j])); } indent(-3); } return null; }
private void setLineMap(Code_attribute attr) { SortedMap<Integer, SortedSet<Integer>> map = new TreeMap<Integer, SortedSet<Integer>>(); SortedSet<Integer> allLines = new TreeSet<Integer>(); for (Attribute a: attr.attributes) { if (a instanceof LineNumberTable_attribute) { LineNumberTable_attribute t = (LineNumberTable_attribute) a; for (LineNumberTable_attribute.Entry e: t.line_number_table) { int start_pc = e.start_pc; int line = e.line_number; SortedSet<Integer> pcLines = map.get(start_pc); if (pcLines == null) { pcLines = new TreeSet<Integer>(); map.put(start_pc, pcLines); } pcLines.add(line); allLines.add(line); } } } lineMap = map; lineList = new ArrayList<Integer>(allLines); }
static int checkMethod(ClassFile cf, String mthd) throws Exception { if (cf.major_version < 52) { throw new RuntimeException("unexpected class file version, in " + cf.getName() + "expected 52, got " + cf.major_version); } int count = 0; for (Method m : cf.methods) { String mname = m.getName(cf.constant_pool); if (mname.equals(mthd)) { for (Attribute a : m.attributes) { if ("Code".equals(a.getName(cf.constant_pool))) { count++; checkMethod(cf.getName(), mname, cf.constant_pool, (Code_attribute) a); } } } } return count; }
@Override public Void visitBootstrapMethods(BootstrapMethods_attribute attr, Void p) { println(Attribute.BootstrapMethods + ":"); for (int i = 0; i < attr.bootstrap_method_specifiers.length ; i++) { BootstrapMethods_attribute.BootstrapMethodSpecifier bsm = attr.bootstrap_method_specifiers[i]; indent(+1); print(i + ": #" + bsm.bootstrap_method_ref + " "); println(constantWriter.stringValue(bsm.bootstrap_method_ref)); indent(+1); println("Method arguments:"); indent(+1); for (int j = 0; j < bsm.bootstrap_arguments.length; j++) { print("#" + bsm.bootstrap_arguments[j] + " "); println(constantWriter.stringValue(bsm.bootstrap_arguments[j])); } indent(-3); } return null; }
private void setLineMap(Code_attribute attr) { SortedMap<Integer, SortedSet<Integer>> map = new TreeMap<>(); SortedSet<Integer> allLines = new TreeSet<>(); for (Attribute a: attr.attributes) { if (a instanceof LineNumberTable_attribute) { LineNumberTable_attribute t = (LineNumberTable_attribute) a; for (LineNumberTable_attribute.Entry e: t.line_number_table) { int start_pc = e.start_pc; int line = e.line_number; SortedSet<Integer> pcLines = map.get(start_pc); if (pcLines == null) { pcLines = new TreeSet<>(); map.put(start_pc, pcLines); } pcLines.add(line); allLines.add(line); } } } lineMap = map; lineList = new ArrayList<>(allLines); }
void verifyBytecode() { File compiledTest = new File("Test.class"); try { ClassFile cf = ClassFile.read(compiledTest); BootstrapMethods_attribute bsm_attr = (BootstrapMethods_attribute)cf .getAttribute(Attribute.BootstrapMethods); int length = bsm_attr.bootstrap_method_specifiers.length; if (length != 1) { throw new Error("Bad number of method specifiers " + "in BootstrapMethods attribute: " + length); } } catch (Exception e) { e.printStackTrace(); throw new Error("error reading " + compiledTest +": " + e); } }
@Test public void testSimpleAnnotation(Path base) throws Exception { Path moduleSrc = base.resolve("module-src"); Path m1 = moduleSrc.resolve("m1x"); tb.writeJavaFiles(m1, "@Deprecated module m1x { }"); Path modulePath = base.resolve("module-path"); Files.createDirectories(modulePath); new JavacTask(tb) .options("--module-source-path", moduleSrc.toString()) .outdir(modulePath) .files(findJavaFiles(m1)) .run() .writeAll(); ClassFile cf = ClassFile.read(modulePath.resolve("m1x").resolve("module-info.class")); RuntimeVisibleAnnotations_attribute annotations = (RuntimeVisibleAnnotations_attribute) cf.attributes.map.get(Attribute.RuntimeVisibleAnnotations); if (annotations == null || annotations.annotations.length != 1) { throw new AssertionError("Annotations not correct!"); } }
static List<Entry> findEntries() throws IOException, ConstantPoolException { ClassFile self = ClassFile.read(NullCheckLineNumberTest.Test.class.getResourceAsStream("NullCheckLineNumberTest$Test.class")); for (Method m : self.methods) { if ("<init>".equals(m.getName(self.constant_pool))) { Code_attribute code_attribute = (Code_attribute)m.attributes.get(Attribute.Code); for (Attribute at : code_attribute.attributes) { if (Attribute.LineNumberTable.equals(at.getName(self.constant_pool))) { return Arrays.stream(((LineNumberTable_attribute)at).line_number_table) .map(e -> new SimpleEntry<> (e.line_number, e.start_pc)) .collect(Collectors.toList()); } } } } return null; }
void checkMethod(ConstantPool constantPool, Method method, AliveRanges ranges) throws InvalidIndex, UnexpectedEntry, ConstantPoolException { Code_attribute code = (Code_attribute) method.attributes.get(Attribute.Code); LocalVariableTable_attribute lvt = (LocalVariableTable_attribute) (code.attributes.get(Attribute.LocalVariableTable)); List<String> infoFromRanges = convertToStringList(ranges); List<String> infoFromLVT = convertToStringList(constantPool, lvt); // infoFromRanges most be contained in infoFromLVT int i = 0; int j = 0; while (i < infoFromRanges.size() && j < infoFromLVT.size()) { int comparison = infoFromRanges.get(i).compareTo(infoFromLVT.get(j)); if (comparison == 0) { i++; j++; } else if (comparison > 0) { j++; } else { break; } } if (i < infoFromRanges.size()) { error(infoFromLVT, infoFromRanges, method.getName(constantPool).toString()); } }
private void test(String src) { addTestCase(src); printf("Testing test case :\n%s\n", src); try { Map<String, ? extends JavaFileObject> classes = compile(src).getClasses(); String outerClassName = classes.containsKey("deprecated") ? "deprecated" : "notDeprecated"; echo("Testing outer class : " + outerClassName); ClassFile cf = readClassFile(classes.get(outerClassName)); Deprecated_attribute attr = (Deprecated_attribute) cf.getAttribute(Attribute.Deprecated); testAttribute(outerClassName, attr, cf); testInnerClasses(cf, classes); testMethods(cf); testFields(cf); } catch (Exception e) { addFailure(e); } }
private void testInnerClasses(ClassFile cf, Map<String, ? extends JavaFileObject> classes) throws ConstantPoolException, IOException { InnerClasses_attribute innerAttr = (InnerClasses_attribute) cf.getAttribute(Attribute.InnerClasses); for (Info innerClass : innerAttr.classes) { String innerClassName = cf.constant_pool. getClassInfo(innerClass.inner_class_info_index).getName(); echo("Testing inner class : " + innerClassName); ClassFile innerCf = readClassFile(classes.get(innerClassName)); Deprecated_attribute attr = (Deprecated_attribute) innerCf.getAttribute(Attribute.Deprecated); String innerClassSimpleName = innerClass.getInnerName(cf.constant_pool); testAttribute(innerClassSimpleName, attr, innerCf); if (innerClassName.contains("Local")) { testMethods(innerCf); testFields(innerCf); } } }
private void assertAttributePresent(ClassFile classFile, String fileName) throws Exception { //We need to count attributes with the same names because there is no appropriate API in the ClassFile. List<SourceFile_attribute> sourceFileAttributes = new ArrayList<>(); for (Attribute a : classFile.attributes.attrs) { if (Attribute.SourceFile.equals(a.getName(classFile.constant_pool))) { sourceFileAttributes.add((SourceFile_attribute) a); } } assertEquals(sourceFileAttributes.size(), 1, "Should be the only SourceFile attribute"); SourceFile_attribute attribute = sourceFileAttributes.get(0); assertEquals(classFile.constant_pool.getUTF8Info(attribute.attribute_name_index).value, Attribute.SourceFile, "Incorrect attribute name"); assertEquals(classFile.constant_pool.getUTF8Info(attribute.sourcefile_index).value, fileName, "Incorrect source file name"); assertEquals(attribute.attribute_length, 2, "Incorrect attribute length"); }
void checkClassFile(final Path path) throws Exception { ClassFile classFile = ClassFile.read( new BufferedInputStream(Files.newInputStream(path))); constantPool = classFile.constant_pool; utf8Index = constantPool.getUTF8Index("STR_TO_LOOK_FOR"); for (Method method: classFile.methods) { if (method.getName(constantPool).equals("methodToLookFor")) { Code_attribute codeAtt = (Code_attribute)method.attributes.get(Attribute.Code); for (Instruction inst: codeAtt.getInstructions()) { inst.accept(codeVisitor, null); } } } Assert.check(numberOfRefToStr == 1, "There should only be one reference to a CONSTANT_String_info structure in the generated code"); }
public void run() throws Exception { ClassFile cf = getClassFile("TypeAnnotationPropagationTest$Test.class"); Method f = null; for (Method m : cf.methods) { if (m.getName(cf.constant_pool).contains("f")) { f = m; break; } } int idx = f.attributes.getIndex(cf.constant_pool, Attribute.Code); Code_attribute cattr = (Code_attribute) f.attributes.get(idx); idx = cattr.attributes.getIndex(cf.constant_pool, Attribute.RuntimeVisibleTypeAnnotations); RuntimeVisibleTypeAnnotations_attribute attr = (RuntimeVisibleTypeAnnotations_attribute) cattr.attributes.get(idx); TypeAnnotation anno = attr.annotations[0]; assertEquals(anno.position.lvarOffset, new int[] {3}, "start_pc"); assertEquals(anno.position.lvarLength, new int[] {8}, "length"); assertEquals(anno.position.lvarIndex, new int[] {1}, "index"); }
void verifyDefaultBody(String classFile) { String workDir = System.getProperty("test.classes"); File file = new File(workDir, classFile); try { final ClassFile cf = ClassFile.read(file); for (Method m : cf.methods) { Code_attribute codeAttr = (Code_attribute)m.attributes.get(Attribute.Code); for (Instruction instr : codeAttr.getInstructions()) { if (instr.getOpcode() == Opcode.INVOKESPECIAL) { int pc_index = instr.getShort(1); CPRefInfo ref = (CPRefInfo)cf.constant_pool.get(pc_index); String className = ref.getClassName(); if (className.equals("BaseInterface")) throw new IllegalStateException("Must not directly refer to TestedInterface"); } } } } catch (Exception e) { e.printStackTrace(); throw new Error("error reading " + file +": " + e); } }
private void checkDebugAttributes(byte[] strippedClassFile) throws IOException, ConstantPoolException { ClassFile classFile = ClassFile.read(new ByteArrayInputStream(strippedClassFile)); String[] debugAttributes = new String[]{ Attribute.LineNumberTable, Attribute.LocalVariableTable, Attribute.LocalVariableTypeTable }; for (Method method : classFile.methods) { String methodName = method.getName(classFile.constant_pool); Code_attribute code = (Code_attribute) method.attributes.get(Attribute.Code); for (String attr : debugAttributes) { if (code.attributes.get(attr) != null) { throw new AssertionError("Debug attribute was not removed: " + attr + " from method " + classFile.getName() + "#" + methodName); } } } }