1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.bcel;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.IOException;
23 import java.util.concurrent.TimeUnit;
24 import java.util.jar.JarEntry;
25 import java.util.jar.JarFile;
26
27 import org.apache.bcel.classfile.ClassParser;
28 import org.apache.bcel.classfile.JavaClass;
29 import org.apache.bcel.classfile.Method;
30 import org.apache.bcel.generic.ClassGen;
31 import org.apache.bcel.generic.InstructionList;
32 import org.apache.bcel.generic.MethodGen;
33 import org.apache.commons.collections4.Predicate;
34 import org.apache.commons.collections4.iterators.EnumerationIterator;
35 import org.apache.commons.collections4.iterators.FilterIterator;
36 import org.apache.commons.collections4.iterators.IteratorIterable;
37 import org.apache.commons.io.IOUtils;
38 import org.openjdk.jmh.annotations.Benchmark;
39 import org.openjdk.jmh.annotations.BenchmarkMode;
40 import org.openjdk.jmh.annotations.Fork;
41 import org.openjdk.jmh.annotations.Measurement;
42 import org.openjdk.jmh.annotations.Mode;
43 import org.openjdk.jmh.annotations.OutputTimeUnit;
44 import org.openjdk.jmh.annotations.Threads;
45 import org.openjdk.jmh.annotations.Warmup;
46 import org.openjdk.jmh.infra.Blackhole;
47
48 @BenchmarkMode(Mode.AverageTime)
49 @Fork(value = 1, jvmArgs = "-server")
50 @Threads(1)
51 @Warmup(iterations = 10)
52 @Measurement(iterations = 20)
53 @OutputTimeUnit(TimeUnit.MILLISECONDS)
54 public class BCELBenchmark {
55
56
57
58
59 @Benchmark
60 public void baseline(Blackhole bh) throws IOException {
61 final JarFile jar = getJarFile();
62 for (JarEntry entry : getClasses(jar)) {
63 final byte[] bytes = IOUtils.toByteArray(jar.getInputStream(entry));
64 bh.consume(bytes);
65 }
66 jar.close();
67 }
68
69 @Benchmark
70 public void generator(Blackhole bh) throws IOException {
71 final JarFile jar = getJarFile();
72 for (JarEntry entry : getClasses(jar)) {
73 final byte[] bytes = IOUtils.toByteArray(jar.getInputStream(entry));
74 final JavaClass clazz = new ClassParser(new ByteArrayInputStream(bytes), entry.getName()).parse();
75 final ClassGen cg = new ClassGen(clazz);
76 for (Method m : cg.getMethods()) {
77 final MethodGen mg = new MethodGen(m, cg.getClassName(), cg.getConstantPool());
78 final InstructionList il = mg.getInstructionList();
79 if (il != null) {
80 mg.getInstructionList().setPositions();
81 mg.setMaxLocals();
82 mg.setMaxStack();
83 }
84 cg.replaceMethod(m, mg.getMethod());
85 }
86 bh.consume(cg.getJavaClass().getBytes());
87 }
88 jar.close();
89 }
90
91 private Iterable<JarEntry> getClasses(JarFile jar) {
92 return new IteratorIterable<>(new FilterIterator<>(new EnumerationIterator<>(jar.entries()), new Predicate<JarEntry>() {
93 @Override
94 public boolean evaluate(JarEntry entry) {
95 return entry.getName().endsWith(JavaClass.EXTENSION);
96 }
97 }));
98 }
99
100 private JarFile getJarFile() throws IOException {
101 final String javaHome = System.getProperty("java.home");
102 return new JarFile(javaHome + "/lib/rt.jar");
103 }
104
105 @Benchmark
106 public void parser(final Blackhole bh) throws IOException {
107 final JarFile jar = getJarFile();
108 for (JarEntry entry : getClasses(jar)) {
109 final byte[] bytes = IOUtils.toByteArray(jar.getInputStream(entry));
110 final JavaClass clazz = new ClassParser(new ByteArrayInputStream(bytes), entry.getName()).parse();
111 bh.consume(clazz);
112 }
113 jar.close();
114 }
115 }