You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

反射调用getMethod时方法名异常:输入与报错名称不符求助

反射调用方法时方法名被截断的异常原因及解决办法

问题描述

调用myClass.getMethod("func_181057_v")时,控制台抛出异常NoSuchMethodException: myClass.v(),输入的方法名与报错中的不一致。已尝试使用.getMethod(..)和.getDeclaredMethod(..),打印.getDeclaredMethods()列表时,.func_181057_v()确实存在,但修改方法名(如改为func_181057__v)时,程序会查找输入的完整名称而非"v"。

相关代码

try {
   Class<?> fmlCommonHandlerClass = Class.forName("net.minecraftforge.fml.common.FMLCommonHandler");
   Class<?> minecraftServerClass = Class.forName("net.minecraft.server.MinecraftServer");
   Class<?> playerListClass = Class.forName("net.minecraft.server.management.PlayerList");

   Method getMinecraftServerInstanceMethod = fmlCommonHandlerClass.getDeclaredMethod("getMinecraftServerInstance");
   Method getPlayerListMethod = minecraftServerClass.getDeclaredMethod("getPlayerList");
   Method getPlayersMethod = playerListClass.getDeclaredMethod("func_181057_v");
} catch (Exception exception) {
   throw new RuntimeException(exception);
}

运行环境

  • Mohist服务器1.12.2 build320
  • Java 1.8.0_361

完整异常信息

[18:25:56 ERROR]: Error occurred while enabling ReflectionExample v1.0-SNAPSHOT (Is it up to date?)
 java.lang.RuntimeException: java.lang.NoSuchMethodException: net.minecraft.server.management.PlayerList.v()
        at com.example.plugin.reflectionExample.ReflectionExample.onEnable(ReflectionExample.java:20) ~[?:?]
        at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:177) ~[JavaPlugin.class:?]
        at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:318) [JavaPluginLoader.class:?]
        at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:399) [SimplePluginManager.class:?]
        at org.bukkit.craftbukkit.v1_12_R1.CraftServer.enablePlugin(CraftServer.java:477) [CraftServer.class:?]
        at org.bukkit.craftbukkit.v1_12_R1.CraftServer.enablePlugins(CraftServer.java:418) [CraftServer.class:?]
        at net.minecraft.server.MinecraftServer.func_71247_a(MinecraftServer.java:383) [MinecraftServer.class:?]
        at net.minecraft.server.dedicated.DedicatedServer.func_71197_b(DedicatedServer.java:315) [nz.class:?]
        at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:590) [MinecraftServer.class:?]
        at java.lang.Thread.run(Unknown Source) [?:1.8.0_361]
Caused by: java.lang.NoSuchMethodException: net.minecraft.server.management.PlayerList.v()
        at java.lang.Class.getMethod(Unknown Source) ~[?:1.8.0_361]
        at com.mohistmc.bukkit.nms.proxy.ProxyClass.getMethod(ProxyClass.java:43) ~[ProxyClass.class:?]
        at com.example.plugin.reflectionExample.ReflectionExample.onEnable(ReflectionExample.java:18) ~[?:?]
        ... 9 more

原因分析

从异常栈可以看到,反射调用被代理到了com.mohistmc.bukkit.nms.proxy.ProxyClass.getMethod,这是Mohist服务器的NMS代理机制导致的:它会自动识别并截断以func_数字_开头的方法名,只保留下划线后的部分(比如func_181057_v会被处理成v)。但实际类中存在的方法名是完整的func_181057_v,所以用截断后的v查找会找不到,用完整名称时又被代理篡改,最终导致匹配失败。

解决办法

方法一:遍历方法列表精确匹配

绕过代理对getDeclaredMethod的篡改,直接遍历类的所有声明方法,通过方法名精确匹配获取目标方法:

Method getPlayersMethod = null;
for (Method method : playerListClass.getDeclaredMethods()) {
    if ("func_181057_v".equals(method.getName())) {
        getPlayersMethod = method;
        break;
    }
}
if (getPlayersMethod == null) {
    throw new NoSuchMethodException("func_181057_v");
}

方法二:获取未被代理的原始类

通过实例对象获取真实的类(代理类的实例实际指向原始类对象),比如先获取MinecraftServer实例,再从中获取PlayerList实例,最后从实例上获取类:

// 先获取MinecraftServer实例
Object minecraftServer = getMinecraftServerInstanceMethod.invoke(null);
// 获取PlayerList实例
Object playerList = getPlayerListMethod.invoke(minecraftServer);
// 从实例获取未被代理的原始类
Class<?> realPlayerListClass = playerList.getClass();
// 此时调用getDeclaredMethod可以正常找到方法
Method getPlayersMethod = realPlayerListClass.getDeclaredMethod("func_181057_v");

方法三:使用Mohist原生反射工具

Mohist提供了专门处理NMS反射的工具类,可以直接使用这些工具来避免代理机制的干扰,这类工具会自动处理方法名的映射问题,具体可参考Mohist官方文档中的反射工具类说明。


内容的提问来源于stack exchange,提问作者Nathalie Kitty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 20:45:15