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

URLClassLoader加载类时访问内部类触发IllegalAccessError的解决方法

问题分析

错误java.lang.IllegalAccessError的核心原因是:外部类myClass和内部类myClass$myInnerClass被不同的类加载器加载,且内部类默认是包访问权限。

在Java模块系统中,未命名模块(unnamed module)的包访问权限仅对同一类加载器加载的同包类开放。当myClass被URLClassLoader加载,而myClass$myInnerClass被应用类加载器(app loader)加载时,JVM会判定两者属于不同的运行时类,包级访问会被直接拒绝。


解决方案

1. 确保两类被同一个类加载器加载(推荐)

使用URLClassLoader加载myClass时,必须让该类加载器能定位到myClass$myInnerClass.class文件:

  • 将包含这两个class文件的目录或JAR路径,添加到URLClassLoader的构造参数中,确保类加载器可以找到内部类的字节码文件。
  • 示例代码:
    // 假设class文件存放在./target/classes目录下
    URL classDir = new File("./target/classes").toURI().toURL();
    URLClassLoader customLoader = new URLClassLoader(new URL[]{classDir});
    
    // 加载外部类,此时内部类会由同一个URLClassLoader加载
    Class<?> myClass = customLoader.loadClass("myClass");
    
    当外部类需要访问内部类时,会使用自身的类加载器去加载内部类,从根源上避免类加载器不一致的问题。

2. 修改内部类的访问权限

如果无法保证同一类加载器,可将内部类改为public,同时显式声明其构造方法为public(默认内部类构造方法为包级权限):

public class myClass {
  public class myInnerClass {
    // 显式声明public构造方法
    public myInnerClass() {}
  }
}

重新编译后,不同类加载器加载的类也能正常访问public权限的内部类。

3. 反射强制访问(应急方案)

若无法修改原代码,可通过反射绕过访问权限检查:

URLClassLoader customLoader = new URLClassLoader(new URL[]{classDir});
Class<?> outerClass = customLoader.loadClass("myClass");
// 实例化外部类
Object outerInstance = outerClass.getDeclaredConstructor().newInstance();

// 加载内部类
Class<?> innerClass = customLoader.loadClass("myClass$myInnerClass");
// 内部类构造方法默认需要传入外部类实例作为参数
Constructor<?> innerConstructor = innerClass.getDeclaredConstructor(outerClass);
// 开启可访问性,绕过权限检查
innerConstructor.setAccessible(true);
Object innerInstance = innerConstructor.newInstance(outerInstance);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 16:15:08