public void write(Object owner, Attributes attrs, ConstantPool constant_pool) { if (attrs != null) { // null checks owner.getClass(); constant_pool.getClass(); this.constant_pool = constant_pool; this.owner = owner; for (Attribute attr: attrs) attr.accept(this, null); } }
protected void readAttributesFor(ClassFile c, Attributes attrs, Element x) { Element container = new Element(); AttributeVisitor av = new AttributeVisitor(this, c); for (Attribute a : attrs) { av.visit(a, container); } if (!keepOrder) { container.sort(); } x.addAll(container); }
public void write(Object owner, Attributes attrs, ConstantPool constant_pool) { if (attrs != null) { Assert.checkNonNull(constant_pool); Assert.checkNonNull(owner); this.constant_pool = constant_pool; this.owner = owner; for (Attribute attr: attrs) attr.accept(this, null); } }
private void addModuleResolutionAttribute(Path classfile, int resolution_flags) throws Exception { ClassFile cf = ClassFile.read(classfile); Attributes attrs = cf.attributes; List<CPInfo> cpData = new ArrayList<>(); cpData.add(null); for (CPInfo info : cf.constant_pool.entries()) { cpData.add(info); if (info.size() == 2) cpData.add(null); } cpData.add(new CONSTANT_Utf8_info(Attribute.ModuleResolution)); ConstantPool newCP = new ConstantPool(cpData.toArray(new CPInfo[0])); ModuleResolution_attribute res = new ModuleResolution_attribute(newCP, resolution_flags); Map<String, Attribute> newAttributeMap = new HashMap<>(attrs.map); newAttributeMap.put(Attribute.ModuleResolution, res); Attributes newAttrs = new Attributes(newAttributeMap); ClassFile newCF = new ClassFile(cf.magic, cf.minor_version, cf.major_version, newCP, cf.access_flags, cf.this_class, cf.super_class, cf.interfaces, cf.fields, cf.methods, newAttrs); try (OutputStream out = Files.newOutputStream(classfile)) { new ClassWriter().write(newCF, out); } }
Signature_attribute getSignature(Attributes attributes) { return (Signature_attribute) attributes.get(Attribute.Signature); }
void checkForAttr(Attributes attrs, String errorMsg, String... attrNames) { for (String attrName : attrNames) { Assert.checkNonNull(attrs.get(attrName), errorMsg); } }
@Test public void testNonZeroOpensInOpen(Path base) throws Exception { Path m1 = base.resolve("m1x"); tb.writeJavaFiles(m1, "module m1x { opens api; }", "package api; public class Api {}"); Path classes = base.resolve("classes"); Path m1Classes = classes.resolve("m1x"); tb.createDirectories(m1Classes); new JavacTask(tb) .options("-XDrawDiagnostics") .outdir(m1Classes) .files(findJavaFiles(m1)) .run(Expect.SUCCESS) .writeAll(); Path miClass = m1Classes.resolve("module-info.class"); ClassFile cf = ClassFile.read(miClass); Module_attribute module = (Module_attribute) cf.attributes.map.get(Attribute.Module); Module_attribute newModule = new Module_attribute(module.attribute_name_index, module.module_name, module.module_flags | Module_attribute.ACC_OPEN, module.module_version_index, module.requires, module.exports, module.opens, module.uses_index, module.provides); Map<String, Attribute> attrs = new HashMap<>(cf.attributes.map); attrs.put(Attribute.Module, newModule); Attributes newAttributes = new Attributes(attrs); ClassFile newClassFile = new ClassFile(cf.magic, cf.minor_version, cf.major_version, cf.constant_pool, cf.access_flags, cf.this_class, cf.super_class, cf.interfaces, cf.fields, cf.methods, newAttributes); try (OutputStream out = Files.newOutputStream(miClass)) { new ClassWriter().write(newClassFile, out); } Path test = base.resolve("test"); tb.writeJavaFiles(test, "package impl; public class Impl extends api.Api {}"); Path testClasses = base.resolve("test-classes"); tb.createDirectories(testClasses); List<String> log = new JavacTask(tb) .options("-XDrawDiagnostics", "--module-path", classes.toString(), "--add-modules", "m1x") .outdir(testClasses) .files(findJavaFiles(test)) .run(Expect.FAIL) .writeAll() .getOutputLines(Task.OutputKind.DIRECT); List<String> expected = Arrays.asList( "- compiler.err.cant.access: m1x.module-info, " + "(compiler.misc.bad.class.file.header: module-info.class, " + "(compiler.misc.module.non.zero.opens: m1x))", "1 error"); if (!expected.equals(log)) throw new Exception("expected output not found: " + log); }
public static void main(String[] args) throws Exception { if (args.length < 2) { System.err.println("Usage: java RemoveMethods classfile output [method...]"); System.exit(-1); } // class file to read Path input = Paths.get(args[0]); // class file to write, if directory then use the name of the input Path output = Paths.get(args[1]); if (Files.isDirectory(output)) output = output.resolve(input.getFileName()); // the methods to remove Set<String> methodsToRemove = new HashSet<>(); int i = 2; while (i < args.length) methodsToRemove.add(args[i++]); // read class file ClassFile cf; try (InputStream in = Files.newInputStream(input)) { cf = ClassFile.read(in); } final int magic = cf.magic; final int major_version = cf.major_version; final int minor_version = cf.minor_version; final ConstantPool cp = cf.constant_pool; final AccessFlags access_flags = cf.access_flags; final int this_class = cf.this_class; final int super_class = cf.super_class; final int[] interfaces = cf.interfaces; final Field[] fields = cf.fields; final Attributes class_attrs = cf.attributes; // remove the requested methods, no signature check at this time Method[] methods = cf.methods; i = 0; while (i < methods.length) { Method m = methods[i]; String name = m.getName(cp); if (methodsToRemove.contains(name)) { int len = methods.length; Method[] newMethods = new Method[len-1]; if (i > 0) System.arraycopy(methods, 0, newMethods, 0, i); int after = methods.length - i - 1; if (after > 0) System.arraycopy(methods, i+1, newMethods, i, after); methods = newMethods; String paramTypes = m.descriptor.getParameterTypes(cp); System.out.format("Removed method %s%s from %s%n", name, paramTypes, cf.getName()); continue; } i++; } // TBD, prune constant pool of entries that are no longer referenced // re-write class file cf = new ClassFile(magic, minor_version, major_version, cp, access_flags, this_class, super_class, interfaces, fields, methods, class_attrs); try (OutputStream out = Files.newOutputStream(output)) { new ClassWriter().write(cf, out); } }
Signature_attribute getSignature(Attributes attributes) { if (options.compat) // javap does not recognize recent attributes return null; return (Signature_attribute) attributes.get(Attribute.Signature); }