Commit fe1d8f16 authored by Eric Bruneton's avatar Eric Bruneton

Delete the examples.

These examples were introduced long before the user guide, which now provides more and better documented examples.
parent 3f8159e0
......@@ -131,59 +131,6 @@ project(':benchmarks:write') {
runWith = ['org.objectweb.asm.GenPerfTest']
}
project(':examples') {
description = "Examples using ${parent.description}"
}
project(':examples:adapt') {
description = "Class transformation example for ${rootProject.description}"
requires = [':asm']
runWith = ['Adapt', 'ArraySet']
}
project(':examples:analysis') {
description = "Static class analysis example for ${rootProject.description}"
requires = [':asm-analysis', ':asm-util']
runWith = ['Analysis']
}
project(':examples:annotations') {
description = "Java 5 annotations example for ${rootProject.description}"
requires = [':asm']
runWith = ['Annotations']
}
project(':examples:attributes') {
description = "Custom attributes example for ${rootProject.description}"
requires = [':asm', ':asm-util']
runWith = ['Attributes']
}
project(':examples:compiler') {
description = "Small compiler example using ${rootProject.description}"
requires = [':asm']
runWith = ['Compile']
}
project(':examples:compiler-indy') {
description = "Invokedynamic example for ${rootProject.description}"
requires = [':asm']
runWith = ['IndyCompile']
}
project(':examples:dependencies') {
description = "Dependency analysis example with ${rootProject.description}"
requires = [':asm']
runWith = ['org.objectweb.asm.depend.DependencyTracker',
project(':asm').jar.outputs.files.singleFile]
}
project(':examples:helloworld') {
description = "Helloworld example for ${rootProject.description}"
requires = [':asm', ':asm-commons']
runWith = ['Helloworld']
}
project(':tools') {
description = "Tools used to build ${parent.description}"
}
......
// ASM: a very small and fast Java bytecode manipulation framework
// Copyright (c) 2000-2011 INRIA, France Telecom
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
/** @author Eric Bruneton */
public class Adapt extends ClassLoader {
@Override
protected synchronized Class<?> loadClass(final String name, final boolean resolve)
throws ClassNotFoundException {
if (name.startsWith("java.")) {
System.err.println("Adapt: loading class '" + name + "' without on the fly adaptation");
return super.loadClass(name, resolve);
} else {
System.err.println("Adapt: loading class '" + name + "' with on the fly adaptation");
}
// gets an input stream to read the bytecode of the class
String resource = name.replace('.', '/') + ".class";
InputStream is = getResourceAsStream(resource);
byte[] b;
// adapts the class on the fly
try {
ClassReader cr = new ClassReader(is);
ClassWriter cw = new ClassWriter(0);
ClassVisitor cv = new TraceFieldClassAdapter(cw);
cr.accept(cv, 0);
b = cw.toByteArray();
} catch (Exception e) {
throw new ClassNotFoundException(name, e);
}
// optional: stores the adapted class on disk
try {
FileOutputStream fos = new FileOutputStream(resource + ".adapted");
fos.write(b);
fos.close();
} catch (IOException e) {
}
// returns the adapted class
return defineClass(name, b, 0, b.length);
}
public static void main(final String args[]) throws Exception {
// loads the application class (in args[0]) with an Adapt class loader
ClassLoader loader = new Adapt();
Class<?> c = loader.loadClass(args[0]);
// calls the 'main' static method of this class with the
// application arguments (in args[1] ... args[n]) as parameter
Method m = c.getMethod("main", new Class<?>[] {String[].class});
String[] applicationArgs = new String[args.length - 1];
System.arraycopy(args, 1, applicationArgs, 0, applicationArgs.length);
m.invoke(null, new Object[] {applicationArgs});
}
}
class TraceFieldClassAdapter extends ClassVisitor implements Opcodes {
private String owner;
public TraceFieldClassAdapter(final ClassVisitor cv) {
super(Opcodes.ASM5, cv);
}
@Override
public void visit(
final int version,
final int access,
final String name,
final String signature,
final String superName,
final String[] interfaces) {
owner = name;
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public FieldVisitor visitField(
final int access,
final String name,
final String desc,
final String signature,
final Object value) {
FieldVisitor fv = super.visitField(access, name, desc, signature, value);
if ((access & ACC_STATIC) == 0) {
Type t = Type.getType(desc);
int size = t.getSize();
// generates getter method
String gDesc = "()" + desc;
MethodVisitor gv = cv.visitMethod(ACC_PRIVATE, "_get" + name, gDesc, null, null);
gv.visitFieldInsn(GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;");
gv.visitLdcInsn("_get" + name + " called");
gv.visitMethodInsn(
INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
gv.visitVarInsn(ALOAD, 0);
gv.visitFieldInsn(GETFIELD, owner, name, desc);
gv.visitInsn(t.getOpcode(IRETURN));
gv.visitMaxs(1 + size, 1);
gv.visitEnd();
// generates setter method
String sDesc = "(" + desc + ")V";
MethodVisitor sv = cv.visitMethod(ACC_PRIVATE, "_set" + name, sDesc, null, null);
sv.visitFieldInsn(GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;");
sv.visitLdcInsn("_set" + name + " called");
sv.visitMethodInsn(
INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
sv.visitVarInsn(ALOAD, 0);
sv.visitVarInsn(t.getOpcode(ILOAD), 1);
sv.visitFieldInsn(PUTFIELD, owner, name, desc);
sv.visitInsn(RETURN);
sv.visitMaxs(1 + size, 1 + size);
sv.visitEnd();
}
return fv;
}
@Override
public MethodVisitor visitMethod(
final int access,
final String name,
final String desc,
final String signature,
final String[] exceptions) {
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
return mv == null ? null : new TraceFieldCodeAdapter(mv, owner);
}
}
class TraceFieldCodeAdapter extends MethodVisitor implements Opcodes {
private String owner;
public TraceFieldCodeAdapter(final MethodVisitor mv, final String owner) {
super(Opcodes.ASM5, mv);
this.owner = owner;
}
@Override
public void visitFieldInsn(
final int opcode, final String owner, final String name, final String desc) {
if (owner.equals(this.owner)) {
if (opcode == GETFIELD) {
// replaces GETFIELD f by INVOKESPECIAL _getf
String gDesc = "()" + desc;
visitMethodInsn(INVOKESPECIAL, owner, "_get" + name, gDesc, false);
return;
} else if (opcode == PUTFIELD) {
// replaces PUTFIELD f by INVOKESPECIAL _setf
String sDesc = "(" + desc + ")V";
visitMethodInsn(INVOKESPECIAL, owner, "_set" + name, sDesc, false);
return;
}
}
super.visitFieldInsn(opcode, owner, name, desc);
}
}
// ASM: a very small and fast Java bytecode manipulation framework
// Copyright (c) 2000-2011 INRIA, France Telecom
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
/** @author Eric Bruneton */
public class ArraySet {
private int[] values = new int[3];
private int size;
public boolean contains(final int v) {
for (int i = 0; i < size; ++i) {
if (values[i] == v) {
return true;
}
}
return false;
}
public void add(final int v) {
if (!contains(v)) {
if (size == values.length) {
System.err.println("[enlarge]");
int[] newValues = new int[values.length + 3];
System.arraycopy(values, 0, newValues, 0, size);
values = newValues;
}
values[size++] = v;
}
}
public void remove(final int v) {
int i = 0;
int j = 0;
while (i < size) {
int u = values[i];
if (u != v) {
values[j++] = u;
}
++i;
}
size = j;
}
// test method
public static void main(final String[] args) {
ArraySet s = new ArraySet();
System.err.println("add 1");
s.add(1);
System.err.println("add 1");
s.add(1);
System.err.println("add 2");
s.add(2);
System.err.println("add 4");
s.add(4);
System.err.println("add 8");
s.add(8);
System.err.println("contains 3 = " + s.contains(3));
System.err.println("contains 1 = " + s.contains(1));
System.err.println("remove 1");
s.remove(1);
System.err.println("contains 1 = " + s.contains(1));
}
}
// ASM: a very small and fast Java bytecode manipulation framework
// Copyright (c) 2000-2011 INRIA, France Telecom
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.IincInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;
import org.objectweb.asm.tree.analysis.Analyzer;
import org.objectweb.asm.tree.analysis.BasicValue;
import org.objectweb.asm.tree.analysis.BasicVerifier;
import org.objectweb.asm.tree.analysis.Frame;
import org.objectweb.asm.tree.analysis.SourceInterpreter;
import org.objectweb.asm.tree.analysis.SourceValue;
import org.objectweb.asm.util.TraceMethodVisitor;
import org.objectweb.asm.util.Textifier;
/** @author Eric Bruneton */
public class Analysis implements Opcodes {
public static void main(final String[] args) throws Exception {
ClassReader cr = new ClassReader("Analysis");
ClassNode cn = new ClassNode();
cr.accept(cn, ClassReader.SKIP_DEBUG);
List<MethodNode> methods = cn.methods;
for (int i = 0; i < methods.size(); ++i) {
MethodNode method = methods.get(i);
if (method.instructions.size() > 0) {
if (!analyze(cn, method)) {
Analyzer<?> a = new Analyzer<BasicValue>(new BasicVerifier());
try {
a.analyze(cn.name, method);
} catch (Exception ignored) {
}
final Frame<?>[] frames = a.getFrames();
Textifier t =
new Textifier() {
@Override
public void visitMaxs(final int maxStack, final int maxLocals) {
for (int i = 0; i < text.size(); ++i) {
StringBuilder s =
new StringBuilder(frames[i] == null ? "null" : frames[i].toString());
while (s.length() < Math.max(20, maxStack + maxLocals + 1)) {
s.append(' ');
}
System.err.print(
Integer.toString(i + 1000).substring(1) + " " + s + " : " + text.get(i));
}
System.err.println();
}
};
MethodVisitor mv = new TraceMethodVisitor(t);
for (int j = 0; j < method.instructions.size(); ++j) {
Object insn = method.instructions.get(j);
((AbstractInsnNode) insn).accept(mv);
}
mv.visitMaxs(0, 0);
}
}
}
}
/*
* Detects unused xSTORE instructions, i.e. xSTORE instructions without at
* least one xLOAD corresponding instruction in their successor instructions
* (in the control flow graph).
*/
public static boolean analyze(final ClassNode c, final MethodNode m) throws Exception {
Analyzer<SourceValue> a = new Analyzer<SourceValue>(new SourceInterpreter());
Frame<SourceValue>[] frames = a.analyze(c.name, m);
// for each xLOAD instruction, we find the xSTORE instructions that can
// produce the value loaded by this instruction, and we put them in
// 'stores'
Set<AbstractInsnNode> stores = new HashSet<AbstractInsnNode>();
for (int i = 0; i < m.instructions.size(); ++i) {
AbstractInsnNode insn = m.instructions.get(i);
int opcode = insn.getOpcode();
if ((opcode >= ILOAD && opcode <= ALOAD) || opcode == IINC) {
int var = opcode == IINC ? ((IincInsnNode) insn).var : ((VarInsnNode) insn).var;
Frame<SourceValue> f = frames[i];
if (f != null) {
Set<AbstractInsnNode> s = f.getLocal(var).insns;
Iterator<AbstractInsnNode> j = s.iterator();
while (j.hasNext()) {
insn = j.next();
if (insn instanceof VarInsnNode) {
stores.add(insn);
}
}
}
}
}
// we then find all the xSTORE instructions that are not in 'stores'
boolean ok = true;
for (int i = 0; i < m.instructions.size(); ++i) {
AbstractInsnNode insn = m.instructions.get(i);
int opcode = insn.getOpcode();
if (opcode >= ISTORE && opcode <= ASTORE) {
if (!stores.contains(insn)) {
ok = false;
System.err.println(
"method " + m.name + ", instruction " + i + ": useless store instruction");
}
}
}
return ok;
}
/*
* Test for the above method, with three useless xSTORE instructions.
*/
public int test(int i, int j) {
i = i + 1; // ok, because i can be read after this point
if (j == 0) {
j = 1; // useless
} else {
try {
j = j - 1; // ok, because j can be accessed in the catch
int k = 0;
if (i > 0) {
k = i - 1;
}
return k;
} catch (Exception e) { // useless ASTORE (e is never used)
j = j + 1; // useless
}
}
return 0;
}
}
// ASM: a very small and fast Java bytecode manipulation framework
// Copyright (c) 2000-2011 INRIA, France Telecom
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
public class Annotations {
public static void foo(final @NotNull String arg) {
System.out.println(arg);
}
public static void main(final String[] args) throws Exception {
System.out.println("Calling foo(null) results in a NullPointerException:");
try {
foo(null);
} catch (Exception e) {
e.printStackTrace(System.out);
}
final String n = Annotations.class.getName();
final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassReader cr = new ClassReader(n);
cr.accept(
new ClassVisitor(Opcodes.ASM4, cw) {
@Override
public MethodVisitor visitMethod(
final int access,
final String name,
final String desc,
final String signature,
final String[] exceptions) {
final Type[] args = Type.getArgumentTypes(desc);
MethodVisitor v = cv.visitMethod(access, name, desc, signature, exceptions);
return new MethodVisitor(Opcodes.ASM5, v) {
private final List<Integer> params = new ArrayList<Integer>();
@Override
public AnnotationVisitor visitParameterAnnotation(
final int parameter, final String desc, final boolean visible) {
AnnotationVisitor av;
av = mv.visitParameterAnnotation(parameter, desc, visible);
if (desc.equals("LNotNull;")) {
params.add(parameter);
}
return av;
}
@Override
public void visitCode() {
int var = (access & Opcodes.ACC_STATIC) == 0 ? 1 : 0;
for (int p = 0; p < params.size(); ++p) {
int param = params.get(p).intValue();
for (int i = 0; i < param; ++i) {
var += args[i].getSize();
}
String c = "java/lang/IllegalArgumentException";
String d = "(Ljava/lang/String;)V";
Label end = new Label();
mv.visitVarInsn(Opcodes.ALOAD, var);
mv.visitJumpInsn(Opcodes.IFNONNULL, end);
mv.visitTypeInsn(Opcodes.NEW, c);
mv.visitInsn(Opcodes.DUP);