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