性能分析器 Profiler

基本信息

属性 值
类型 mod 列表扫描 / 可转换目标发现工具
实现类 net.vfyjxf.nechar.utils.Profiler
触发方式 /nech profile
线程优先级 Thread.MIN_PRIORITY
产出文件 logs/necharacters-profiler.txt(Gson 缩进 JSON)
扫描范围 游戏目录下的 mods 目录(递归)

目的

本模组的拼音支持完全依赖"把其他模组界面里的 String.contains / String.matches / Pattern.matcher 换成拼音实现"。默认目标列表只能覆盖已知模组(见 默认转换目标列表),Profiler 就是用来发现尚未收录、但同样调用了这些方法的目标方法的辅助工具——扫描结果可直接作为 AdditionalTransformerStringList / AdditionalTransformerRegExpList 的素材。

执行流程

步骤 方法 行为
1 run() 以 new File("mods") 为根目录调用 scanDirectory,结果数组存入 Report.jars
2 scanDirectory(File) listFiles() 遍历:.jar 文件 → ZipFile 打开后 scanJar;子目录 → 递归扫描并把结果并入列表
3 scanJar(ZipFile, callback) 遍历 jar 内条目
4 scanClass(InputStream, ...) 对每个 .class 用 ASM ClassReader 解析,按四类签名收集方法
5 过滤 若一个 jar 的四类结果全部为空,则不加入报告(cbkJar.accept(ret) 不执行)
6 输出 NechCommand 把 Report 以 Gson 缩进格式写入 logs/necharacters-profiler.txt

scanJar 收集的四类签名

每个 .class 条目内按方法遍历指令流,命中下列特征即记录 类名:方法名:方法描述符(/ 已替换为 .)并 break(每个方法只记录首个命中):

报告字段 指令特征 归属转换器
methodsString INVOKEVIRTUAL java/lang/String.contains 描述符 (Ljava/lang/CharSequence;)Z TransformerString
methodsRegExp INVOKEVIRTUAL java/lang/String.matches 描述符 (Ljava/lang/String;)Z TransformerRegExp
methodsRegExp INVOKEVIRTUAL java/util/regex/Pattern.matcher 描述符 (Ljava/lang/CharSequence;)Ljava/util/regex/Matcher; TransformerRegExp
methodsStrsKt INVOKESTATIC kotlin/text/StringsKt.contains 描述符 (Ljava/lang/CharSequence;Ljava/lang/CharSequence;Z)Z 无对应转换器(仅报告)
methodsSuffix NEW 指令的目标为 net/minecraft/client/util/SuffixArray、cgx 或 cgz 无对应转换器(仅报告)

注意 methodsSuffix 的判定条件用括号写法为 NEW && (SuffixArray || cgx) || cgz——按 Java 运算符优先级,cgz 分支不受 NEW 与前两个类的限制。

容错处理

情形 处理
class 文件 entry.getSize() + 4 > Integer.MAX_VALUE 打印日志 Class file ... is too large, skip. 并跳过该类
读取条目 IOException 打印 Fail to read file ... , skip. 并继续
ClassReader.accept 抛异常 若 classNode.name 非空则打印 File decoding of class ... failed. Try to continue. 继续;否则包装成 IOException 抛出
打开 jar IOException e.printStackTrace(),跳过该文件

mcmod.info 解析

scanJar 额外识别名为 mcmod.info 的条目并用 Gson 解析进 JarContainer.mods:

  1. 先尝试解析为 ModContainer[](数组形式);
  2. 捕获异常后回退解析为单个 ModContainer;
  3. 两者都失败则打印 Fail to read mod info in jar file ..., skip.。

每个 ModContainer 字段:modid、name、version、mcversion、url、authorList。

报告结构

类 字段
Report(公开) version(占位常量 @VERSION@)、mcversion(MinecraftForge.MC_VERSION)、date(实例初始化块中用 SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH) + GMT 时区生成)、jars(JarContainer[])
JarContainer(私有) mods(ModContainer[])、methodsString、methodsRegExp、methodsSuffix、methodsStrsKt(均为 String[])
ModContainer(私有) 见上

Report 的 date 字段在实例初始化块中计算,因此每次 new Report() 都会重新取当前时间。

相关条目