【问题标题】:Java - How to properly circumvent Illegal access exception in this caseJava - 在这种情况下如何正确规避非法访问异常
【发布时间】:2019-01-12 20:56:09
【问题描述】:

我遇到了这个奇怪的问题,即使(我认为)我将所有内容都设置为可以正确访问,但我仍然收到 IllegalAccessException。

java.lang.IllegalAccessException: 类 com.sasha.eventsys.SimpleEventManager 无法访问类的成员 com.sasha.proxy.discord.DiscordMain 带有修饰符“private”

public void invokeEvent(SimpleEvent e){
    registeredMethods.forEach(method -> {
        if (method.getParameterTypes()[0] == e.getClass()){
            try {
                Class clasz = method.getDeclaringClass();
                for (Field field : clasz.getFields()) {
                    field.setAccessible(true);
                }
                for (Method meth : clasz.getMethods()) {
                    meth.setAccessible(true);
                }
                for (Constructor<?> constructor : clasz.getConstructors()) {
                    constructor.setAccessible(true);
                }
                method.setAccessible(true);
                method.invoke(clasz.newInstance(), e);
            }
            catch (Exception ex){
                System.out.println("FATAL EXCEPTION DURING " + e.getClass().getName() + "'s EXECUTION");
                ex.printStackTrace();
            }
        }
    });
}

这是调用该方法的代码。从理论上讲,那些 for 循环应该将所有内容设置为可访问,对吧?

@SimpleEventHandler
public void onMcMsgRecieved(MinecraftMessageRecievedEvent e){
    if(Config.doDiscord) {
        DiscordMain.theChannel = DiscordMain.findTheServer(jda.getTextChannelsByName(Config.channelName,false));
        if (Config.aestheticDiscord) {
            DiscordMain.renderViewport(e.getPlainText(), DiscordMain.theChannel, Caches.messagesRecieved==0);
            Caches.messagesRecieved++;
        }
        else {
            DiscordMain.theChannel.sendMessage("```html\n" + e.getPlainText().replace("discord.gg", "zozzle.gg").replace("`", "'").replaceAll("\247[^z]", "") + "\n```").submit();
        }
        Webhooks.pushToHook("```html\n" + e.getPlainText().replace("discord.gg", "zozzle.gg").replace("`", "'").replaceAll("\247[^z]", "") + "\n```");
    }
}

这就是它应该无法访问某些东西的地方。作为参考,此块中调用的所有字段和方法都是公共或公共静态的,所以我不明白为什么会出现问题。

【问题讨论】:

  • 你能发布整个错误吗?

标签: java reflection


【解决方案1】:

Field 的反射实例、方法、构造函数等只是一个副本,.setAccessible 只影响那个副本,所以像

这样的代码
            for (Field field : clasz.getFields()) {
                field.setAccessible(true);
            }

什么都不做。

在您的情况下,我猜.newInstance 会抛出该错误,因为无参数构造函数是私有的?如果是这样,那么您需要通过.getDeclaredConstructor() 方法手动获取构造函数并将其设置为可访问并使用它来创建新实例。

【讨论】:

  • 是的,但是 OP 在调用之前设置了可访问性为真,所以你的答案没有解释异常
  • @Bohemian OP 也没有解释他在哪里得到了那个错误。但看看我的编辑,也许是关于 .newInstance
  • 感谢您的评论,看来您的回答很可能是正确的。
  • 那也接受吧,关于问题,不就是你要改的这个字段也是静态的吗?正如我在您的代码中看到的许多静态用法,然后只需传递 null:field.set(null, newValue)(但这样数量的静态代码看起来很糟糕)
猜你喜欢
  • 2013-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-06
  • 2012-06-06
  • 2022-01-11
相关资源
最近更新 更多