"""Find every class whose constant pool references a named method. Used to answer "who actually calls this" across a whole jar, where grepping source would only show the decompiled view and javap would need one command per class. python find_callers.py """ import os import struct import sys sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from struct_diff import Reader, read_constant_pool, CONSTANT_UTF8, SKIP_TWO_SLOT def method_names(path): with open(path, 'rb') as handle: data = handle.read() reader = Reader(data) if reader.u4() != 0xCAFEBABE: return None reader.u2() reader.u2() pool = read_constant_pool(reader) names = [] for index, entry in enumerate(pool): if isinstance(entry, str): names.append(entry) return names def main(): root, needle = sys.argv[1], sys.argv[2] hits = [] for base, _dirs, files in os.walk(root): for name in files: if not name.endswith('.class'): continue full = os.path.join(base, name) key = os.path.relpath(full, root).replace(os.sep, '/') try: names = method_names(full) except Exception: continue if names is None: continue if any(n == needle or n.startswith(needle) for n in names): hits.append(key) print('%d class(es) reference %s' % (len(hits), needle)) for key in hits: print(' %s' % key) if __name__ == '__main__': main()