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