#!/usr/bin/env python3 """Removes MethodParameters attributes from .class files (in place). JDK 21+ javac always emits them for inner-class constructors, and older d8 releases crash on the nameless ones. They are only reflection metadata, so dropping them is safe. usage: strip_method_params.py file.class... """ import struct import sys def strip(path): d = open(path, "rb").read() n = struct.unpack(">H", d[8:10])[0] p, i, utf8 = 10, 1, {} while i < n: t = d[p] if t == 1: ln = struct.unpack(">H", d[p + 1:p + 3])[0] utf8[i] = d[p + 3:p + 3 + ln] p += 3 + ln elif t in (3, 4, 9, 10, 11, 12, 17, 18): p += 5 elif t in (5, 6): p += 9 i += 1 elif t in (7, 8, 16, 19, 20): p += 3 elif t == 15: p += 4 else: raise ValueError("bad constant tag %d in %s" % (t, path)) i += 1 out = bytearray(d[:p]) p_access = p ifaces = struct.unpack(">H", d[p + 6:p + 8])[0] p += 8 + 2 * ifaces out += d[p_access:p] def members(p, drop): count = struct.unpack(">H", d[p:p + 2])[0] buf = bytearray(d[p:p + 2]) p += 2 for _ in range(count): buf += d[p:p + 6] acount = struct.unpack(">H", d[p + 6:p + 8])[0] p += 8 kept = [] for _ in range(acount): name, ln = struct.unpack(">HI", d[p:p + 6]) if utf8.get(name) != drop: kept.append(d[p:p + 6 + ln]) p += 6 + ln buf += struct.pack(">H", len(kept)) + b"".join(kept) return p, buf p, fields = members(p, None) out += fields p, methods = members(p, b"MethodParameters") out += methods out += d[p:] if bytes(out) != d: open(path, "wb").write(bytes(out)) return 1 return 0 changed = sum(strip(f) for f in sys.argv[1:]) print("stripped MethodParameters from %d class files" % changed)