使用URLClassLoader加载类后调用构造函数触发IllegalAccessException
问题:为何无法访问已加载类的public构造函数?
尝试从文件系统(不在主程序类路径中)加载类并获取实例,代码如下:
try { File folder = new File("/tmp/"); URLClassLoader loader = URLClassLoader.newInstance(new URL[] {folder.toURI().toURL()}); Class clazz = loader.loadClass("testpkg.test"); Constructor constructor = clazz.getConstructor(); Object instance = constructor.newInstance(); } catch (Exception e) { e.printStackTrace(); }
被加载的类文件位于/tmp/testpkg/test.class,其源码为:
package testpkg; class test{ public test(){ System.out.println("I am the constructor!"); } }
执行Object instance = constructor.newInstance();时触发运行时错误,错误信息:
java.lang.IllegalAccessException: Class tmp.ClassLoadingFun can not access a member of class testpkg.test with modifiers "public" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102) at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296) at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288) at java.lang.reflect.Constructor.newInstance(Constructor.java:413) at tmp.ClassLoadingFun.<init>(ClassLoadingFun.java:16) at tmp.ClassLoadingFun.main(ClassLoadingFun.java:23)
修改包名或类名会提前触发找不到类的错误,说明类加载成功,但构造函数调用失败。
解答
问题出在类本身的访问权限上:你的test类没有添加public修饰符,默认是包级私有访问权限。即使构造函数是public,但类本身对外不可见,外部包的tmp.ClassLoadingFun无法直接访问这个类的成员,包括构造函数。
解决方法有两种:
- 修改
test类的访问修饰符为public:
package testpkg; public class test{ // 添加public修饰符 public test(){ System.out.println("I am the constructor!"); } }
重新编译后,外部就能正常通过反射创建实例。
- 通过反射强制开启构造函数的访问权限:
在调用newInstance()之前,设置构造器的accessible属性为true,绕过访问检查:
Constructor constructor = clazz.getConstructor(); constructor.setAccessible(true); // 添加这一行 Object instance = constructor.newInstance();
内容的提问来源于stack exchange,提问作者roediGERhard
相关产品推荐
相关产品推荐

