尝试从具有不同ClassLoader的类读取受保护属性时出现IllegalAccessException

时间:2012-12-31 18:49:51

标签: java classloader protected

我有以下文件:

src/
 |- cltest/
 |   |- Main.class
 |   |- Test.class
 |   `- TestingClassLoader.class
 `- data (a class cltest.LoadedClass without an extension)

Main.java:

package cltest;

public class Main {
  protected static String field = "TestTestTest";
  public static void main(String[] args) throws Exception {
    Class.forName("cltest.Test");
    Class.forName("cltest.LoadedClass", true, new TestingClassLoader());
  }
}

Test.java和/ data

package cltest;

public class Test /* or LoadedClass for /data file */ {
  static {
    System.out.println(Main.field);
  }
}

TestingClassLoader.java

package cltest;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.CodeSource;
import java.security.ProtectionDomain;

public class TestingClassLoader extends ClassLoader {
  public Class<?> findClass(String name) throws ClassNotFoundException {
    try {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      InputStream is = this.getClass().getResourceAsStream("/data");
      byte[] buf = new byte[256]; int r;
      while ((r = is.read(buf)) != -1) baos.write(buf, 0, r);
      byte[] data = baos.toByteArray();

      return defineClass(null, data, 0, data.length);
    } catch (Exception e) {
      throw new ClassNotFoundException(name, e);
    }
  }
}

此代码在行Class.forName("cltest.LoadedClass", true, new TestingClassLoader());上给出了错误:

TestTestTest //  (output of 1st Class.forName() call)
Exception in thread "main" java.lang.IllegalAccessError: tried to access field cltest.Main.field from class cltest.LoadedClass
  at cltest.LoadedClass.<clinit>(LoadedClass.java:5)
  at java.lang.Class.forName0(Native Method)
  at java.lang.Class.forName(Unknown Source)
  at cltest.Main.main(Main.java:7)

我该如何解决?

1 个答案:

答案 0 :(得分:2)

实现此功能的唯一方法是将LoadedClass和Main放在同一个类加载器中(如果类具有相同的包名类加载器,则它们只在同一个包中。)

你正在谈论一个&#34;插件&#34;需要访问main的受保护方法。这是一个插件系统的糟糕设计。如果您控制这些类,则将必要的方法设为public而不是protected。