File: ManyMethodsBenchmarkApp.java

package info (click to toggle)
openjdk-24 24.0.2%2B12-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 831,900 kB
  • sloc: java: 5,677,020; cpp: 1,323,154; xml: 1,320,524; ansic: 486,889; asm: 405,131; objc: 21,025; sh: 15,221; javascript: 11,049; python: 8,222; makefile: 2,504; perl: 357; awk: 351; sed: 172; pascal: 103; exp: 54; jsp: 24; csh: 3
file content (141 lines) | stat: -rw-r--r-- 5,652 bytes parent folder | download | duplicates (16)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
 * Copyright 2015 Google Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

import java.io.File;
import java.io.FileWriter;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.List;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

/**
 * A manual benchmark of the JVMTI RedefineClasses when a
 * single class (and its parent) contains many methods.
 */
public class ManyMethodsBenchmarkApp {
     // Limit is 64k but we can not put such many as the CP limit is 32k.
     // In practice, it means a real limit is much lower (less than 22000).
    static final int METHOD_COUNT = 20000;

    static Class<?> loadClassInNewClassLoader(String className) throws Exception {
        URL[] urls = { new File(".").toURI().toURL() };
        URLClassLoader ucl = new URLClassLoader(urls, null);
        Class<?> klazz = Class.forName(className, true, ucl);
        return klazz;
    }

    static void benchmarkClassOperations(String className) throws Exception {
        Class<?> klazz = loadClassInNewClassLoader(className);

        Method[] methods = klazz.getDeclaredMethods();
        if (methods.length != METHOD_COUNT) {
            throw new AssertionError("unexpected method count: " + methods.length +
                                     " expected: " + METHOD_COUNT);
        }

        methods = klazz.getMethods();
        // returned methods includes those inherited from Object
        int objectMethodSlop = 100;
        if (methods.length <= METHOD_COUNT ||
            methods.length >= METHOD_COUNT + objectMethodSlop) {
            throw new AssertionError("unexpected method count: " + methods.length);
        }

        // Invoke methods to make them appear in the constant pool cache
        Object obj = klazz.newInstance();
        Object[] args = new Object[0];
        for (Method m: methods) {
            try {
                Class<?>[] types = m.getParameterTypes();
                String     name  = m.getName();
             // System.out.println("method: " + name + "; argno: " + types.length);
                if (types.length == 0 && name.length() == 2 && name.startsWith("f")) {
                    m.invoke(obj, args);
                }
            } catch (InvocationTargetException ex) {
                ex.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        System.out.println("test started: ManyMethodsBenchmarkApp");

        // Create source files with many methods
        File base = new File("Base.java");
        try (FileWriter fw = new FileWriter(base)) {
            fw.write("public class Base {\n");
            final int L = 10;
            // Each of the first L methods makes calls to its own chunk of METHOD_COUNT/L methods
            for (int k = 0; k < L; k++) {
                fw.write("    public void f" + k + "() {\n");
                int shift = (k == 0) ? L : 0;
                for (int i = (k * (METHOD_COUNT/L)) + shift; i < (k + 1) * METHOD_COUNT/L; i++) {
                    fw.write("        f" + i + "();\n");
                }
                fw.write("    }\n");
            }

            // The rest of (METHOD_COUNT - L) methods have empty body
            for (int i = L; i < METHOD_COUNT; i++) {
                fw.write("    public static void f" + i + "() {}\n");
            }
            fw.write("}\n");
        }

        // Compile the generated source files.
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        List<File> files = Arrays.asList(new File[] { base });
        try (StandardJavaFileManager fileManager =
             compiler.getStandardFileManager(null, null, null)) {
            compiler.getTask(null, fileManager, null, null, null,
                fileManager.getJavaFileObjectsFromFiles(files))
                .call();
        }

        benchmarkClassOperations("Base");

        ManyMethodsBenchmarkAgent.instr();

        // Cleanup
        base.delete();
        new File("Base.class").delete();
        if (!ManyMethodsBenchmarkAgent.completed) {
            throw new Exception("ERROR: ManyMethodsBenchmarkAgent did not complete.");
        }

        if (ManyMethodsBenchmarkAgent.fail) {
            throw new Exception("ERROR: ManyMethodsBenchmarkAgent failed.");
        } else {
            System.out.println("ManyMethodsBenchmarkAgent succeeded.");
        }
        System.out.println("test finished: ManyMethodsBenchmarkApp");
    }
}