62,614
社区成员
发帖
与我相关
我的任务
分享
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class Test {
public class MyLoader extends ClassLoader {
private final String path = getClass().getResource("/").getPath();
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] b = getData(name);
return defineClass(name, b, 0, b.length);
}
private byte[] getData(String url) {
byte[] b = null;
try (FileInputStream reader = new FileInputStream(new StringBuffer(
path).append(url.replace('.', File.separatorChar))
.append(".class").toString())) {
b = new byte[reader.available()];
reader.read(b, 0, b.length);
} catch (IOException e) {
e.printStackTrace();
}
return b;
}
}
public static void main(String[] args) throws Exception {
new Test().foo();
}
private void foo() throws Exception {
Class<?> cls = Foo.class;
/* 使用MyLoader加载非public类 */
// cls = new MyLoader().findClass(Foo.class.getName());
Object obj = cls.newInstance();// java.lang.IllegalAccessException异常
cls.getDeclaredMethod("bar").invoke(obj);
}
}
/*public*/ class Foo {
public void bar() {
System.out.println("asdfghjkl");
}
}
private void foo() throws Exception {
Class<?> cls = Foo.class;
/* non-public Foo */
cls = new MyLoader().findClass(Foo.class.getName());
// Object obj = cls.newInstance(); // java.lang.IllegalAccessException
Constructor<?> con = cls.getDeclaredConstructor();
con.setAccessible(true);
Object obj = con.newInstance();
Method method = cls.getDeclaredMethod("bar");
method.setAccessible(true);
method.invoke(obj);
}
}
[/quote]
对头,就是反射的限制,加载器没限制,加载还是可以正常加载的,但是获取实例的时候有私有成员安全验证。所以问题不在加载而在反射。。。
private void foo() throws Exception {
Class<?> cls = Foo.class;
/* non-public Foo */
cls = new MyLoader().findClass(Foo.class.getName());
// Object obj = cls.newInstance(); // java.lang.IllegalAccessException
Constructor<?> con = cls.getDeclaredConstructor();
con.setAccessible(true);
Object obj = con.newInstance();
Method method = cls.getDeclaredMethod("bar");
method.setAccessible(true);
method.invoke(obj);
}
}
Constructor<T> tmpConstructor = cachedConstructor;
// Security check (same as in java.lang.reflect.Constructor)
int modifiers = tmpConstructor.getModifiers();
if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
if (newInstanceCallerCache != caller) {
Reflection.ensureMemberAccess(caller, this, null, modifiers);
newInstanceCallerCache = caller;
}
}
// Run constructor
public T newInstance()
throws InstantiationException, IllegalAccessException
{
if (System.getSecurityManager() != null) {
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
}
return newInstance0();
}