Commit a4bf8cc8 authored by Eric Bruneton's avatar Eric Bruneton

Merge branch 'delete-all-examples' into 'master'

Delete the examples.

See merge request !53
parents 26dc3c8d fe1d8f16
......@@ -135,59 +135,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);
mv.visitLdcInsn("Argument " + param + " must not be null");
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, c, "<init>", d, false);
mv.visitInsn(Opcodes.ATHROW);
mv.visitLabel(end);
}
}
};
}
},
0);
Class<?> c =
new ClassLoader() {
@Override
public Class<?> loadClass(final String name) throws ClassNotFoundException {
if (name.equals(n)) {
byte[] b = cw.toByteArray();
return defineClass(name, b, 0, b.length);
}
return super.loadClass(name);
}
}.loadClass(n);
System.out.println();
System.out.println(
"Calling foo(null) on the transformed class results" + " in an IllegalArgumentException:");
Method m = c.getMethod("foo", new Class<?>[] {String.class});
try {
m.invoke(null, new Object[] {null});
} catch (InvocationTargetException e) {
e.getCause().printStackTrace(System.out);
}
}
}
// 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.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.CLASS)
public @interface NotNull {
String value() default "";
}
// 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