View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.bcel;
19  
20  import static org.junit.jupiter.api.Assertions.fail;
21  
22  import java.io.ByteArrayInputStream;
23  import java.io.File;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.util.Arrays;
27  import java.util.Enumeration;
28  import java.util.jar.JarEntry;
29  import java.util.jar.JarFile;
30  
31  import org.apache.bcel.classfile.ClassParser;
32  import org.apache.bcel.classfile.JavaClass;
33  import org.apache.bcel.classfile.Method;
34  import org.apache.bcel.generic.ClassGen;
35  import org.apache.bcel.generic.InstructionList;
36  import org.apache.bcel.generic.MethodGen;
37  import org.junit.jupiter.api.Test;
38  
39  public final class PerformanceTest {
40  
41      private static final boolean REPORT = Boolean.parseBoolean(System.getProperty("PerformanceTest.report", "true"));
42  
43      private static byte[] read(final InputStream is) throws IOException {
44          if (is == null) {
45              throw new IOException("Class not found");
46          }
47          byte[] b = new byte[is.available()];
48          int len = 0;
49          while (true) {
50              final int n = is.read(b, len, b.length - len);
51              if (n == -1) {
52                  if (len < b.length) {
53                      b = Arrays.copyOf(b, len);
54                  }
55                  return b;
56              }
57              len += n;
58              if (len == b.length) {
59                  final byte[] c = new byte[b.length + 1000];
60                  System.arraycopy(b, 0, c, 0, len);
61                  b = c;
62              }
63          }
64      }
65  
66      private static void test(final File lib) throws IOException {
67          final NanoTimer total = new NanoTimer();
68          final NanoTimer parseTime = new NanoTimer();
69          final NanoTimer cgenTime = new NanoTimer();
70          final NanoTimer mgenTime = new NanoTimer();
71          final NanoTimer mserTime = new NanoTimer();
72          final NanoTimer serTime = new NanoTimer();
73  
74          System.out.println("Parsing " + lib);
75  
76          total.start();
77          try (JarFile jar = new JarFile(lib)) {
78              final Enumeration<?> en = jar.entries();
79  
80              while (en.hasMoreElements()) {
81                  final JarEntry e = (JarEntry) en.nextElement();
82                  if (e.getName().endsWith(JavaClass.EXTENSION)) {
83                      byte[] bytes;
84                      try (InputStream in = jar.getInputStream(e)) {
85                          bytes = read(in);
86                      }
87  
88                      parseTime.start();
89                      final JavaClass clazz = new ClassParser(new ByteArrayInputStream(bytes), e.getName()).parse();
90                      parseTime.stop();
91  
92                      cgenTime.start();
93                      final ClassGen cg = new ClassGen(clazz);
94                      cgenTime.stop();
95  
96                      final Method[] methods = cg.getMethods();
97                      for (final Method m : methods) {
98                          mgenTime.start();
99                          final MethodGen mg = new MethodGen(m, cg.getClassName(), cg.getConstantPool());
100                         final InstructionList il = mg.getInstructionList();
101                         mgenTime.stop();
102 
103                         mserTime.start();
104                         if (il != null) {
105                             mg.getInstructionList().setPositions();
106                             mg.setMaxLocals();
107                             mg.setMaxStack();
108                         }
109                         cg.replaceMethod(m, mg.getMethod());
110                         mserTime.stop();
111                     }
112 
113                     serTime.start();
114                     cg.getJavaClass().getBytes();
115                     serTime.stop();
116                 }
117             }
118         }
119         total.stop();
120         if (REPORT) {
121             System.out.println("ClassParser.parse: " + parseTime);
122             System.out.println("ClassGen.init: " + cgenTime);
123             System.out.println("MethodGen.init: " + mgenTime);
124             System.out.println("MethodGen.getMethod: " + mserTime);
125             System.out.println("ClassGen.getJavaClass.getBytes: " + serTime);
126             System.out.println("Total: " + total);
127             System.out.println();
128         }
129     }
130 
131     @Test
132     public void testPerformance() {
133         final File javaLib = new File(System.getProperty("java.home"), "lib");
134         javaLib.listFiles(file -> {
135             if (file.getName().endsWith(".jar")) {
136                 try {
137                     test(file);
138                 } catch (final IOException e) {
139                     fail(e.getMessage());
140                 }
141             }
142             return false;
143         });
144     }
145 
146 }