xml*_*lmx 3 java reflection constructor runtime-error exception
我想定义一个自定义类加载器来在运行时加载我自己的类.
然而, Class.newInstance即使我定义了零参数构造函数总是失败.
异常消息是:
java.lang.IllegalAccessException:类Hello无法使用修饰符"public"访问类Test的成员
为什么?
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
class CustomClassLoader extends ClassLoader {
private Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
public String toString() {
return CustomClassLoader.class.getName();
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
if (classes.containsKey(name)) {
return classes.get(name);
}
byte[] classData;
try {
classData = loadClassData(name);
} catch (IOException e) {
throw new ClassNotFoundException("Class [" + name
+ "] could not be found", e);
}
Class<?> c = defineClass(name, classData, 0, classData.length);
resolveClass(c);
classes.put(name, c);
return c;
}
private byte[] loadClassData(String name) throws IOException {
BufferedInputStream in = new BufferedInputStream(
ClassLoader.getSystemResourceAsStream(name.replace(".", "/")
+ ".class"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
int i;
while ((i = in.read()) != -1) {
out.write(i);
}
in.close();
byte[] classData = out.toByteArray();
out.close();
return classData;
}
}
class Test
{
public Test()
{}
public void Hello()
{}
}
public class Hello {
public static void main(String[] args)
{
try {
CustomClassLoader loader = new CustomClassLoader();
Class<?> c = loader.findClass("Test"); // OK!
Object o = c.newInstance(); // ALWAYS FAIL!
}
catch (Exception e)
{
String s = e.getMessage();
// s is "java.lang.IllegalAccessException: Class Hello can not access"
// " a member of class Test with modifiers "public""
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题是您的Test类是使用默认(包)作用域声明的,但在运行时,您Hello和Test类位于不同的包中.
Java中类的名称(唯一标识符)是完全限定类名和加载它的类加载器的组合:
在运行时,类或接口不是由其名称单独确定,而是由一对确定:它的二进制名称(第4.2.1节)及其定义的类加载器.每个这样的类或接口都属于一个运行时包.类或接口的运行时包由包名称和类或接口的类加载器定义.(JVMS 5.3)
在这种情况下,Test该类由下游类加载器加载,因此它的(默认)包不被认为是Hello(由系统类加载器加载)所在的相同(默认)包.因此,你不要因为类本身不是公共的,所以可以访问构造函数.
如果您创建Test单独的公共顶级类或使用反射使其可用,则此示例将起作用.
| 归档时间: |
|
| 查看次数: |
4465 次 |
| 最近记录: |