3

我有以下文件:

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

主.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);
  }
}

测试类加载器.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)

我该如何解决?

4

1 回答 1

2

唯一可行的方法是使 LoadedClass 和 Main 在同一个类加载器中(只有当它们具有相同的包名类加载器时,类才真正在同一个包中)。

你谈论一个需要访问main的受保护方法的“插件”。对于插件系统来说,这是一个糟糕的设计。如果您控制这些类,则将必要的方法设为公开而不是受保护。

于 2012-12-31T22:29:27.843 回答