Most Used Method Out There

What java method is referenced by the most classes in the most popular JARs I can find in the maven repository? Here’s the program.

package io.github.math_ias;

import java.io.IOException;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.InvalidPathException;

import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassModel;
import java.lang.classfile.MethodModel;

import java.lang.classfile.constantpool.PoolEntry;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.classfile.constantpool.MethodRefEntry;
import java.lang.classfile.constantpool.InterfaceMethodRefEntry;

import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;
import java.util.Comparator;
import java.util.SortedSet;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Compile like ...
 * javac --enable-preview -source 23 src/io/github/math_ias/MyCounter.java -d target
 */
public class MyCounter {
  static record ClassMethod(String clazz, String method) {}
  static record ClassMethodCount(String clazz, String method, Integer count) {}

  static Comparator<ClassMethodCount> CLASS_METHOD_COUNT_COMPARATOR =
    Comparator.comparingInt(ClassMethodCount::count);

  static void pushNewCount(ClassMethodCount classMethodCount, TreeSet<ClassMethodCount> set) {
    set.add(classMethodCount);
    if (set.size() > 5) {
      set.pollFirst();
    }
  }

  public static void main(String[] args) {
    if (args.length != 1) {
      System.err.println("Expected exactly 1 argument, the root directory.");
      System.exit(-1);
    }
    Path rootPath = null;
    try {
      rootPath = Path.of(args[0]);
    } catch (InvalidPathException ipe) {
      System.err.println("Expected first arg to be a valid root path (does not parse).");
      ipe.printStackTrace(System.err);
      System.exit(-1);
    }
    if (!Files.exists(rootPath)) {
      System.err.println("Expected first arg to be a valid root path (does not exist).");
      System.exit(-1);
    }

    ConcurrentHashMap<ClassMethod, Integer> map = new ConcurrentHashMap();

    try {
      Files.walk(rootPath)
      .parallel()
      // This lambda is likely repeating work Files.walk already does,
      // plus this file extension business is nasty,
      // but I'm betting that I can beat xargs without optimizing it.
      .filter((Path path) ->
        !Files.isDirectory(path) &&
        path.getFileName().toString().endsWith(".class")
      )
      .forEach((Path path) -> addMethodsToMap(
        path
      , map
      ));
    } catch (IOException ioe) {
      System.err.println("Unexpected error occurred while traversing file tree.");
      ioe.printStackTrace();
      System.exit(-1);
    }

    TreeSet<ClassMethodCount> sortedSet =
      new TreeSet<ClassMethodCount>(CLASS_METHOD_COUNT_COMPARATOR);
    map.entrySet().forEach((Map.Entry<ClassMethod, Integer> mapEntry) ->
      pushNewCount(
        new ClassMethodCount(
          mapEntry.getKey().clazz()
        , mapEntry.getKey().method()
        , mapEntry.getValue()
        )
      , sortedSet
      )
    );

    sortedSet.forEach((ClassMethodCount classMethodCount) ->
      System.out.println(
        String.format(
          "%d %s.%s"
        , classMethodCount.count()
        , classMethodCount.clazz()
        , classMethodCount.method()
        )
      )
    );

    System.exit(0);
  }

  static Integer mergeInts(Integer left, Integer right) { return left + right; }

  public static void addMethodsToMap(
    Path path
  , ConcurrentHashMap<ClassMethod, Integer> map
  ) {
    try {
      ClassModel classModel =
        ClassFile.of()
          .parse(path);
      Iterator<PoolEntry> iterator = classModel.constantPool().iterator();
      while (iterator.hasNext()) {
        PoolEntry poolEntry = iterator.next();
        switch (poolEntry) {
          case MethodRefEntry methodRefEntry:
            map.merge(
              new ClassMethod(
                methodRefEntry.owner().name().stringValue()
              , methodRefEntry.name().stringValue()
              )
            , 1
            , MyCounter::mergeInts
            );
            break;
          case InterfaceMethodRefEntry interfaceMethodRefEntry:
            map.merge(
              new ClassMethod(
                interfaceMethodRefEntry.owner().name().stringValue()
              , interfaceMethodRefEntry.name().stringValue()
              )
            , 1
            , MyCounter::mergeInts
            );
            break;
          default: // Do nothing.
        }
      }
    } catch (IOException io) {
      System.err.println(String.format("Failed to read path %s, skipping.", path.toString()));
      io.printStackTrace(System.err);
    }
  }
}
% java --enable-preview io.github.math_ias.MyCounter ../../jars
1377 clojure/lang/IFn.invoke
1384 java/lang/StringBuilder.<init>
2312 clojure/lang/AFunction.<init>
2721 java/lang/StringBuilder.append
5916 java/lang/Object.<init>

Nice. The init method. And that total count matches what the other tool shows.

% java --enable-preview io.github.math_ias.MyMain jars java/lang/Object "<init>" "()V" | wc -l
  5916