package ex10; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public class Profiler { private static final ConcurrentMap> methodInvocations = new ConcurrentHashMap<>(); private static final Map> methodDeclarations = new HashMap<>(); private static final Map> inheritedMethods = new HashMap<>(); static { Runtime.getRuntime().addShutdownHook(new Thread(() -> { for (final String className : methodInvocations.keySet()) { System.out.println("=== Class Name: " + className + " ==="); for (final String method : methodDeclarations.getOrDefault(className, Set.of())) { System.out.println("Declared: " + method); } for (final String method : inheritedMethods.getOrDefault(className, Set.of())) { System.out.println("Inherited: " + method); } for (final String method : methodInvocations.get(className)) { System.out.println("Executed: " + className.replace('.', '/') + "." + method); } } })); } private Profiler() { } private static void register(final String className, final String methodName, final Map> methods) { methods.computeIfAbsent(className, ignored -> Collections.synchronizedSet(new HashSet<>())) .add(methodName); } public static void registerInvoke(final String className, final String methodName) { register(className, methodName, methodInvocations); } public static void registerDeclared(final String className, final String methodName) { register(className, methodName, methodDeclarations); } public static void registerInherited(final String className, final String methodName) { register(className, methodName, inheritedMethods); } }