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.apache.commons.lang3.SystemProperties;
38  import org.junit.jupiter.api.Test;
39  
40  public final class PerformanceTest {
41  
42      private static final boolean REPORT = Boolean.parseBoolean(System.getProperty("PerformanceTest.report", "true"));
43  
44      private static byte[] read(final InputStream is) throws IOException {
45          if (is == null) {
46              throw new IOException("Class not found");
47          }
48          byte[] b = new byte[is.available()];
49          int len = 0;
50          while (true) {
51              final int n = is.read(b, len, b.length - len);
52              if (n == -1) {
53                  if (len < b.length) {
54                      b = Arrays.copyOf(b, len);
55                  }
56                  return b;
57              }
58              len += n;
59              if (len == b.length) {
60                  final byte[] c = new byte[b.length + 1000];
61                  System.arraycopy(b, 0, c, 0, len);
62                  b = c;
63              }
64          }
65      }
66  
67      private static void test(final File lib) throws IOException {
68          final NanoTimer total = new NanoTimer();
69          final NanoTimer parseTime = new NanoTimer();
70          final NanoTimer cgenTime = new NanoTimer();
71          final NanoTimer mgenTime = new NanoTimer();
72          final NanoTimer mserTime = new NanoTimer();
73          final NanoTimer serTime = new NanoTimer();
74  
75          System.out.println("Parsing " + lib);
76  
77          total.start();
78          try (JarFile jar = new JarFile(lib)) {
79              final Enumeration<?> en = jar.entries();
80  
81              while (en.hasMoreElements()) {
82                  final JarEntry e = (JarEntry) en.nextElement();
83                  if (e.getName().endsWith(JavaClass.EXTENSION)) {
84                      byte[] bytes;
85                      try (InputStream in = jar.getInputStream(e)) {
86                          bytes = read(in);
87                      }
88  
89                      parseTime.start();
90                      final JavaClass clazz = new ClassParser(new ByteArrayInputStream(bytes), e.getName()).parse();
91                      parseTime.stop();
92  
93                      cgenTime.start();
94                      final ClassGen cg = new ClassGen(clazz);
95                      cgenTime.stop();
96  
97                      final Method[] methods = cg.getMethods();
98                      for (final Method m : methods) {
99                          mgenTime.start();
100                         final MethodGen mg = new MethodGen(m, cg.getClassName(), cg.getConstantPool());
101                         final InstructionList il = mg.getInstructionList();
102                         mgenTime.stop();
103 
104                         mserTime.start();
105                         if (il != null) {
106                             mg.getInstructionList().setPositions();
107                             mg.setMaxLocals();
108                             mg.setMaxStack();
109                         }
110                         cg.replaceMethod(m, mg.getMethod());
111                         mserTime.stop();
112                     }
113 
114                     serTime.start();
115                     cg.getJavaClass().getBytes();
116                     serTime.stop();
117                 }
118             }
119         }
120         total.stop();
121         if (REPORT) {
122             System.out.println("ClassParser.parse: " + parseTime);
123             System.out.println("ClassGen.init: " + cgenTime);
124             System.out.println("MethodGen.init: " + mgenTime);
125             System.out.println("MethodGen.getMethod: " + mserTime);
126             System.out.println("ClassGen.getJavaClass.getBytes: " + serTime);
127             System.out.println("Total: " + total);
128             System.out.println();
129         }
130     }
131 
132     @Test
133     public void testPerformance() {
134         final File javaLib = new File(SystemProperties.getJavaHome(), "lib");
135         javaLib.listFiles(file -> {
136             if (file.getName().endsWith(".jar")) {
137                 try {
138                     test(file);
139                 } catch (final IOException e) {
140                     fail(e.getMessage());
141                 }
142             }
143             return false;
144         });
145     }
146 
147 }